先来热身a=('a','b','c')c=copy.copy(a)d=copy.deepcopy(a)ifc==d:print("c和d的值相等")ifid(c)==id(d):print("c和d的地址相等")想想是什么印在最后?什么是深拷贝和浅拷贝深拷贝是指在复制一个对象时,如果该对象持有对其他对象的引用,则复制时将被复制的对象和被引用的对象一起复制。浅拷贝只复制当前对象和它持有的索引,而不是索引指向的对象。让我举一个例子。比如当前有一个列表a=[1,2,3],b=[3,4,a],[3,4,a]对象持有[1,2,3]对象时b的引用被深拷贝,a对象会一起被拷贝,但不会被浅拷贝。a=[1,2,3]b=[4,5,6,a]浅拷贝bc=copy.copy(b)此时修改a对象会影响ca.append(8)c[4,5,6,[1,2,3,8]]深拷贝b后,再修改a,不会影响dd=copy.deepcopy(b)d[4,5,6,[1,2,3,8]]a.append(66)d[4,5,6,[1,2,3,8]当深拷贝和浅拷贝遇到上面的可变和不可变对象时会发生什么使用可变数据结构以列表为例,我们来看一下元组的不可变结构,在进行深拷贝和浅拷贝时是固定不变的。a=(1,2,3)b=copy.copy(a)c=copy.deepcopy(a)print(id(a))print(id(b))print(id(c))输出:450277689645027768964502776896来自结果发现a,b,c的内存地址大部分是相同的,所以在复制不可变对象时,无论是浅拷贝还是深拷贝,都不会在内存中重新开辟新的地址,它只是原始对象的副本。对象添加引用。如果不可变对象摘要包含对可变对象的引用怎么办?a1=[1,2,3]a=(1,2,3,a1)b=copy.copy(a)c=copy.deepcopy(a)print(id(a))print(id(b))print(id(c))输出:450273028845027302884503232240b是浅拷贝生成的对象和原对象a的内存地址相同,c是深拷贝生成的对象,发现内存地址不同从原始对象a的地址开始。也就是说,如果一个不可变对象持有对一个可变对象的引用,那么在进行深拷贝时,会在内存中创建一个新的地址来存放该对象。回到文章开头提出的问题,就是复制不可变对象,而不可变对象不持有可变对象的引用,所以两个打印语句都会执行。
