引用,浅拷贝,深拷贝
引用
无论是可变数据类型还是不可变的(指内部元素,如下图第一个示例中的a内部的整型是不可变的,内部嵌套的列表是可变的),内存地址也会直接引用过来。
# 不可变数据类型a=[1,2,3,4,5,6]print('a的内存地址为:',id(a))b=aprint('b的内存地址为:',id(a))b[0]=5print('修改b[0]的值后a的值为:',a)print('修改b的值后a的内存地址为:',id(a))print('修改b[0]的值后b的值为:',b)print('修改b的值后b的内存地址为:',id(a))a的内存地址为:2661007521408b的内存地址为:2661007521408修改b[0]的值后a的值为:[5,2,3,4,5,6]修改b的值后a的内存地址为:2661007521408修改b[0]的值后b的值为:[5,2,3,4,5,6]修改b的值后b的内存地址为:2661007521408#可变数据类型a=[1,2,3,[1,2,3],4,5,6]print('a的内存地址为:',id(a))b=aprint('b的内存地址为:',id(a))b[3]=[1,1,3]print('修改b[0]的值后a的值为:',a)print('修改b的值后a的内存地址为:',id(b))print('修改b[0]的值后b的值为:',b)print('修改b的值后b的内存地址为:',id(b))a的内存地址为:2255144316352b的内存地址为:2255144316352修改b[3]的值后a的值为:[1,2,3,[1,1,3],4,5,6]修改b[3]的值后a的内存地址为:2255144316352修改b[3]的值后b的值为:[1,2,3,[1,1,3],4,5,6]修改b[3]的值后b的内存地址为:2255144316352浅拷贝
浅拷贝只会拷贝最外层的内存地址,将拷贝后的值重新分配内存空间,内部的可变数据类型的数据还是引用的原来的。因此,对于不可变数据数据类型,如果浅拷贝后更改数据,原数据不会发生变化;对于可变数据类型,更改内部的数据后,原数据也会跟着发生变化
# 修改不可变数据类型的值a=[1,2,3,[1,2,3],4,5,6]print('a的内存地址为:',id(a))b=copy.copy(a)print('b的内存地址为:',id(b))b[0]=5print('修改b[0]的值后a的值为:',a)print('修改b的值后a的内存地址为:',id(a))print('修改b[0]的值后b的值为:',b)print('修改b的值后b的内存地址为:',id(b))a的内存地址为:1967541742656b的内存地址为:1967541742912#浅拷贝将拷贝后的值重新分配内存空间修改b[0]的值后a的值为:[1,2,3,[1,2,3],4,5,6]# 修改的是整型,所以a的值不变修改b的值后a的内存地址为:1967541742656修改b[0]的值后b的值为:[5,2,3,[1,2,3],4,5,6]# 变的只有b的值修改b的值后b的内存地址为:1967541742912#修改整个可变数据类型的值,原对象不受影响a=[1,2,3,[1,2,3],4,5,6]print('a的内存地址为:',id(a))b=copy.copy(a)print('b的内存地址为:',id(b))b[3]=[1,1,5]# 将b[3]的整个值给替换了,print('修改b[0]的值后a的值为:',a)print('修改b的值后a的内存地址为:',id(a))print('修改b[0]的值后b的值为:',b)print('修改b的值后b的内存地址为:',id(b))a的内存地址为:2258999209408b的内存地址为:2258999209600修改b[0]的值后a的值为:[1,2,3,[1,2,3],4,5,6]修改b的值后a的内存地址为:2258999209408修改b[0]的值后b的值为:[1,2,3,[1,1,5],4,5,6]修改b的值后b的内存地址为:2258999209600# 只修改嵌套列表中的其中一个元素的值,原列表会跟着变化a=[1,2,3,[1,2,3],4,5,6]print('a的内存地址为:',id(a))b=copy.copy(a)print('b的内存地址为:',id(b))b[3][0]=0print('修改b[0]的值后a的值为:',a)print('修改b的值后a的内存地址为:',id(a))print('修改b[0]的值后b的值为:',b)print('修改b的值后b的内存地址为:',id(b))a的内存地址为:2184038935616b的内存地址为:2184038935872修改b[0]的值后a的值为:[1,2,3,[0,2,3],4,5,6]修改b的值后a的内存地址为:2184038935616修改b[0]的值后b的值为:[1,2,3,[0,2,3],4,5,6]修改b的值后b的内存地址为:2184038935872上述,在将b[3] 完全替换和只修改其中一个值,引起的a的变化原因是:在b=copy.copy(a)后,虽然b将[1,2,3,[1,2,3],4,5,6]整个列表重新放在了另一个存储空间中,但是浅拷贝只复制对象本身,也就是只复制最外面的一层,a和b里面的[1,2,3]指向的还是同一个内存地址。在将b[3]完全替换为[1,1,3]后,这是另一个列表,和[1,2,3]指向的不再是同一个内存地址,所以a不会变化。但是如果只修改b[3][0]=0,是直接对[1,2,3]这个内存地址进行的修改,所以a会跟着变化
深拷贝
深拷贝和浅拷贝一样,也会将拷贝后的数据放到另一个存储空间中,不同的是,深拷贝递归复制所有子对象,完全独立。也就是说,无论如何修改b的值,a的值都不会变。
# 修改不可变数据,只改变b,不会改变aa=[1,2,3,[1,2,3],4,5,6]print('a的内存地址为:',id(a))b=copy.deepcopy(a)print('b的内存地址为:',id(b))b[0]=0print('修改b[0]的值后a的值为:',a)print('修改b的值后a的内存地址为:',id(a))print('修改b[0]的值后b的值为:',b)print('修改b的值后b的内存地址为:',id(b))a的内存地址为:2298910436544b的内存地址为:2298910436736修改b[0]的值后a的值为:[1,2,3,[1,2,3],4,5,6]修改b的值后a的内存地址为:2298910436544修改b[0]的值后b的值为:[0,2,3,[1,2,3],4,5,6]修改b的值后b的内存地址为:2298910436736#将内部嵌套列表完全修改,只改变b,不会改变aa=[1,2,3,[1,2,3],4,5,6]print('a的内存地址为:',id(a))b=copy.deepcopy(a)print('b的内存地址为:',id(b))b[3]=[1,1,3]print('修改b[0]的值后a的值为:',a)print('修改b的值后a的内存地址为:',id(a))print('修改b[0]的值后b的值为:',b)print('修改b的值后b的内存地址为:',id(b))a的内存地址为:2329156546048b的内存地址为:2329156546240修改b[0]的值后a的值为:[1,2,3,[1,2,3],4,5,6]修改b的值后a的内存地址为:2329156546048修改b[0]的值后b的值为:[1,2,3,[1,1,3],4,5,6]修改b的值后b的内存地址为:2329156546240#修改内部嵌套列表的其中一个元素,只改变b,不会改变aa=[1,2,3,[1,2,3],4,5,6]print('a的内存地址为:',id(a))b=copy.deepcopy(a)print('b的内存地址为:',id(b))b[3][0]=0print('修改b[0]的值后a的值为:',a)print('修改b的值后a的内存地址为:',id(a))print('修改b[0]的值后b的值为:',b)print('修改b的值后b的内存地址为:',id(b))a的内存地址为:2344290446528b的内存地址为:2344290446720修改b[0]的值后a的值为:[1,2,3,[1,2,3],4,5,6]修改b的值后a的内存地址为:2344290446528修改b[0]的值后b的值为:[1,2,3,[0,2,3],4,5,6]修改b的值后b的内存地址为:2344290446720总结:
引用:直接复制所有元素,不会放到新的存储空间
浅拷贝:只复制最外层的,内部的嵌套数据共享存储空间
深拷贝:逐层递归复制,所有数据都被放到一个新的存储空间
