关于python的copy模块内的浅拷贝和深拷贝

Python 中赋值语句不复制对象,而是在目标和对象之间创建绑定 (bindings) 关系,即复制的是对象的引用。对于自身可变(如列表)或者包含可变项的集合对象(如嵌套列表),有必要生成其副本用于改变操作,而避免改变原对象。

所以对于自身不可变的对象,如元组,copy操作没有意义,本质都是赋值,复制对象引用且无法改变。

 

下面讨论可变对象(如列表)的深浅拷贝情况。

1、浅拷贝(shallow):copy.copy(),浅拷贝会复制可变对象的第一层的所有引用。

新建列表a=[1,2,[3,4,[5,6]]] ,变量a里面保存的是内存地址比如101,a指向101,访问a找到101,101三个元素位置保存了另外三个内存地址,即保存整数1的1011,整数2的1012,列表[3,4,[5,6]]的102。102三个元素位置也保存了另外三个内存地址1013,1014,103,同样,103保存着1015,1016。

b=a,赋值操作,b里面保存的跟a完全一样,b也指向101,所以两者有一方变,另一方也跟着变。

c=a.copy(),浅拷贝,在计算机内存中新开辟一块新空间201,存放第一层的引用,201三个元素位指向的地址与101相同。

 

进行操作c[0]=11,即201的第一个位置指向发生了改变,不再指向1011的整数1,而是指向2011的整数11,这时c的值为[11,2,[3,4,[5,6]]],而a、b的值不变。

 

 

接着进行操作:c[2][0]=33,很显然,改变的这个引用是abc三者所共有的,所以abc的值,都发生了改变

 

 

 

同样,列表c新增一个元素c.append("tqs"),那也不关a、b什么事:

 

 

2、深拷贝(deep):copy.deepcopy(),深拷贝会构造一个新的复合对象,然后递归的将原始对象内所有不可变对象的引用和可变对象的副本插入其中。

a=[1,2,[3,4,[5,"6"]

b=a

c=copy.deepcopy(a)

 

 

了解了浅拷贝之后,深拷贝原理就一目了然了。就是将原始对象内所有层次的可变对象都找个新的内存地址去保存其副本,对于不可变对象如int,str,则直接复制引用即可。此时对c进行的任何操作都不会影响到a和b。

posted @ 2022-12-01 01:21  天青色wy  阅读(123)  评论(0编辑  收藏  举报