目录
一、前言:
二、深拷贝与浅拷贝的异同:
1.相同点:
2.不同点:
3.形象说明:
注意:
三、浅拷贝:
3.1.1浅拷贝示意图:
3.1.2示意图说明
1.对象与子对象(元素)的关系:
2.对象:
3.元素【子对象】:
3.2修改对象:
3.3修改元素(子对象):
3.3.1修改元素(子对象)--可变
3.3.1修改元素(子对象)--不可变
3.4浅拷贝结论:
四、深拷贝:
4.1深拷贝示意图:
4.2深拷贝:
4.3深拷贝结论:
五、《后续》
5.1修改对象:
结论2:
5.2修改元素(子对象)
5.2.1修改元素-----可变:
结论3:
5.2.2修改元素-----不可变:
结论4:
一、前言:
一、对象与元素、可变与不可变
(1)对象:
对象有存储地址id【就好像某个地址的快递仓库】,对象中的元素都有一个地址id【就像仓库的某某货架】
(2)赋值对象与指向对象的元素:
赋值对象或【指向对象】(对象中的元素)有不同的类型【数字,字符串,列表,字典,集合,元组】
(3)可变类型与不可变类型:
定义:可变就是增删改查之后,对象或元素的存储id不会发生改变,反之就是不可变。
1.可变类型:其中【列表,字典,集合】是可变类型
2.不可变类型:【数字,字符串,元组】是不可变数据类型
list1 = [[1, 2], (30, 40),'kkk']
(4)举例: 例如以上的列表list1中,有[1, 2]、(30, 40)、'kkk'三个元素,首先列表本身list1是可变的类型,元素[1, 2]是可变的,元素(30, 40)和'kkk'是不可变的
二、深拷贝与浅拷贝的异同:
1.相同点:
无论深拷贝还是浅拷贝都会创建一个新对象。即:拷贝出来的对象的id不同。
2.不同点:
浅拷贝:只拷贝了对象,对象内的元素并不会发生拷贝。
深拷贝:不仅拷贝对象,对象内的元素也会发生拷贝。
3.形象说明:
深拷贝与浅拷贝形象说明:
首先,有一个数据类型[1,5,6],此时这个数据虽然类型有自己的存储id位置,
但是没有什么意义,因为没有“赋值”给其他的对象,在计算机中“数据没有赋值是没有意义的”。
然后,将数据类型[1,5,6]赋值给一个对象A,也就是A=[1,5,6],此时有了一个对象A,指向了“对象[1,5,6]”,他们是两个不同的id,只是此时是赋值的关系。
然后,深拷贝与浅拷贝都会生成一个新的对象,且与原来的对象是不同的。
然后,浅拷贝---B=copy(A):
生成了一个新的对象B,没有生成新的“指向对象”,就原来的“指向对象”,
他们三者的关系是:A----->[1,5,6]<------B
也就是:浅拷贝得到的【不同对象的“指向对象”是同一个】-----会存在共享部分,也有独立部分
然后,深拷贝--C=deepcopy(A)
生成了一个新的对象C,也生成了一个新的“指向对象”,
他们四者间的关系:A----->[1,5,6]
C----->[1,5,6]
也就是:深拷贝得到的【不同对象的“指向对象”是不同的】-----完全独立
注意:
'''
如果上面的三者的关系:赋值对象{对象},指向对象,子对象(元素)
没有清楚就不要往下看,不然可能会晕。。。
哈哈哈哈.....
对象可能有子对象[元素],子对象[元素]还有可能有次子对象[元素].......
'''
如A=[8,(9,10),[11,12,(13,14)]]
赋值对象----A
指向对象----[8,(9,10),[11,12,(13,14)]]
一代子对象(元素)----8、(9,10)、[11,12,(13,14)] 三个一代子元素
二代子对象(元素)----9、10、11、12、(13,14) 五个二代子元素
。。。。。。依次类推
三、浅拷贝:
3.1.1浅拷贝示意图:
(图示1)
因为a,b,c三个子对象(元素)是可变类型,所以AB是共享abc的,你变我也变。
因为’kkk‘和d是不可变类型的子对象(元素),所以是AB不共享kkk‘和d的,你变我不变。
(如下)
3.1.2示意图说明
1.对象与子对象(元素)的关系:
对象可以包含子对象(元素),对象也可以不包含子对象(元素)。
比如:A1=[[1,2],{'mame':'Marx','age':'23},'kkk',(30,40),{'Aa','33',14,23}]
B2=123
对象 A1包含了3个子对象和1个元素
对象B2没有包含子对象
2.对象:
不管被复制的对象A是不可变的还是可变的,浅拷贝都会生成一个新的对象。
不管被复制的对象A是不可变的还是可变的,如果直接修改对象,那么浅拷贝得到的对象都不会随之改变。
总结:浅拷贝后,如果直接修改对象,双方不会同步改变。
3.元素【子对象】:
对象有可能会包含子对象【元素】,也就是嵌套。比如元组中有【列表/元组】:([1,2],'name','age',(8,9)),列表中有【字典/元组】:[{'age':12},'age',(11,19)]
子对象【元素】也有可变与不可变的区分。
修改:如果被修改的子对象是不可变的,那么两个对象不会同时改变。
如果被修改的子对象是可变的,那么两个对象同时改变。
总结:浅拷贝后,如果修改子对象是可变的,那么两个对象同时改变。反之就是不会同时改变。
1.浅拷贝得到的可变子对象共享,不可变子对象独立。
2.改变共享同时变,改变独立对象不互相影响。
3.2修改对象:
结论1:直接修改对象,那么浅拷贝得到的对象都不会随之改变。
实例:A.append(3)
# encoding=utf-8
import copy
A = [[1, 2], (30, 40), 'kkk']
# A=([1,2],8,9)
B = copy.copy(A)
print(id(A), id(B))
print(A,B)
print(A is B)
print(A[0] is B[0])
print(A[1] is B[1])
print(A[2] is B[2])
print('=============================================')
A.append(3)
print(id(A), id(B))
print(A,B)
print(A is B)
print(A[0] is B[0])
print(A[1] is B[1])
print(A[2] is B[2])
运行结果:没有同时改变
3.3修改元素(子对象):
3.3.1修改元素(子对象)--可变
结论2:修改子对象是可变的,那么两个对象同时改变
实例:A[0].append(3)
# encoding=utf-8
import copy
A = [[1, 2], (30, 40), 'kkk']
# A=([1,2],8,9)
B = copy.copy(A)
print(id(A), id(B))
print(A,B)
print(A is B)
print(A[0] is B[0])
print(A[1] is B[1])
print(A[2] is B[2])
print('=============================================')
'''修改可变子对象'''
A[0].append(3)
print(id(A), id(B))
print(A,B)
print(A is B)
print(A[0] is B[0])
print(A[1] is B[1])
print(A[2] is B[2])
运行结果:同时改变
3.3.1修改元素(子对象)--不可变
结论3:修改子对象是不可变的,那么两个对象不会同时改变
实例:A[1]+=(50,)
# encoding=utf-8
import copy
A = [[1, 2], (30, 40), 'kkk']
# A=([1,2],8,9)
B = copy.copy(A)
print(id(A), id(B))
print(A,B)
print(A is B)
print(A[0] is B[0])
print(A[1] is B[1])
print(A[2] is B[2])
print('=============================================')
'''修改不可变子对象'''
A[1]+=(50,)
print(id(A), id(B))
print(A,B)
print(A is B)
print(A[0] is B[0])
print(A[1] is B[1])
print(A[2] is B[2])
运行结果:不同时改变
3.4浅拷贝结论:
结论1:浅拷贝会生成一个新的对象。
结论2:浅拷贝的两个前后对象会共享可变元素(可变子对象)。是否共享决定了他们是否会同步改变。
结论3:直接修改对象,另一个不会同步改变。
结论4:如果修改的子对象是可变的【也就是共享的】,那么二者同步改变。
如果修改的子对象是不可变的【也就是不共享的】,那么二者不会同步改变。
浅拷贝的结论还是下面这张图
四、深拷贝:
4.1深拷贝示意图:
4.2深拷贝:
1.深拷贝后生成了新的一个赋值对象和一个指向对象。
2.两个赋值对象分别指向了两个不同的指向对象。
3.两个赋值对象没有改变前的“指向对象的内容是相同”(注意:相同不代表是同一个)的==,但却是不同的两个指向对象 is'''。
4.深拷贝完全拷贝了父对象及其子对象,两者是完全独立的。
实例如下:
#encoding=UTF-8
from copy import deepcopy
A=[[1, 2], (30, 40),'kkk']
"""1.查看A的存储地址"""
print(id(A))
print(id(A[0]))
print(id(A[1]))
print(id(A[2]))
print('*'*10)
#深拷贝一个对象
B=deepcopy(A)
"""2.查看B的存储地址"""
print(id(B))
print(id(B[0]))
print(id(B[1]))
print(id(B[2]))
"""3.结论1:深拷贝生成的对象完全开辟了新的存储地址,所以有如下判断:"""
print(A is B) #A并不是B false
print(A==B) #A和B是相同的 true
print(A[0] is B[0]) #A[0]并不是B[0] false
print(A[0]==B[0]) #A[0]和B[0]是相同的 true
深拷贝完全拷贝了父对象及其子对象,两者是完全独立的
4.3深拷贝结论:
结论:深拷贝完全拷贝了父对象及其子对象,两者是完全独立的,互不再影响。
====================================================================
五、《后续》
从这里开始其实已经是说元素的可变性了,与深拷贝关系不大了,因为深拷贝的两个对象完全独立=====================================================================
5.1修改对象:
结论2:
1.深拷贝得到对象与原对象完全独立,两个对象互不再影响。【下面2.3其实是解释】
2.修改哪个对象,那么只影响被修改的对象,对另外一个不影响。
3.修改的对象是可变类型,那么被修改的对象的id不会发生变化。
修改的对象是不可以变类型,那么被修改的对象的id会发生变化。
实例1:直接在后面添加:A.append(33)
因为此时的改变对象A本身是列表,是可变类型,所以改变前后A的id没有发生改变
#encoding=UTF-8
from copy import deepcopy
A=[[1, 2], (30, 40),'kkk']
print('==追加前==>')
#深拷贝一个对象
B=deepcopy(A)
print(A,'\n',B)
print(id(A),'\n',id(B))
"""追加一个元素"""
A.append(33)
print('=追加后==>')
print(A,'\n',B)
print(id(A),'\n',id(B))
"""因为此时的改变对象A本身是列表,是可变类型,所以改变前后A的id没有发生改变"""
#小试一下自行判断
print(A is B)
print(A==B)
print(A[0] is B[0])
print(A[0]==B[0])
5.2修改元素(子对象)
5.2.1修改元素-----可变:
结论3:
1. 修改对象中的可变元素:
被改变对象的元素是可变类型,所以改变前后被修改的元素的id是不变的。
实例二:在可变元素后添加:A[0].append(3)
因为被改变对象的元素A[0]是可变类型,所以改变前后A[0]元素的id是不变的
#encoding=UTF-8
from copy import deepcopy
A=[[1, 2], (30, 40),'kkk']
print('==追加前==>')
#深拷贝一个对象
B=deepcopy(A)
print(A,'\n',B)
print(id(A),'\n',id(B))
print(id(A[0]))
"""可变元素追加一个元素"""
A[0].append(3)
print('=追加后==>')
print(A,'\n',B)
print(id(A),'\n',id(B))
print(id(A[0]))
"""此时因为被改变对象的元素A[0]是可变类型,所以改变前后A[0]元素的id是不变的"""
#小试一下自行判断
print(A is B)
print(A==B)
print(A[0] is B[0])
print(A[0]==B[0])
5.2.2修改元素-----不可变:
结论4:
1. 修改对象中的不可变元素:
被改变对象的元素是不可变类型,所以改变前后被修改的元素的id是随之改变。
实例三:在不可变元素后添加:A[1]+=(60,)文章来源:https://www.toymoban.com/news/detail-675104.html
因为此时被改变的元素A[1]是不可变的,所以改变前后的元素A[1]的id发生了变化文章来源地址https://www.toymoban.com/news/detail-675104.html
#encoding=UTF-8
from copy import deepcopy
A=[[1, 2], (30, 40),'kkk']
print('==追加前==>')
#深拷贝一个对象
B=deepcopy(A)
print(A,'\n',B)
print(id(A),'\n',id(B))
print(id(A[1]))
"""不可变元素追加一个元素"""
A[1]+=(60,)
print('=追加后==>')
print(A,'\n',B)
print(id(A),'\n',id(B))
print(id(A[1]))
"""因为此时被改变的元素A[1]是不可变的,所以改变前后的元素A[1]的id发生了变化"""
#小试一下自行判断
print(A is B)
print(A==B)
print(A[1] is B[1])
print(A[1]==B[1])
到了这里,关于python-浅拷贝(copy)与深拷贝(deepcopy)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!