python中深拷贝和浅拷贝,python浅拷贝和深拷贝详解
要弄清楚Python中的明拷贝和暗拷贝,需要理解以下概念:
可变引用对象(可变对象,不可变对象)-切片复制(轻复制,深复制)
在Python中一切都是对象。
甚至类型本身也是一个对象,而类型对象
Python中的变量不同于C/C /Java中的变量。它指的是一个对象的引用。Python是一种动态类型。程序运行时,会根据对象的类型来确认变量的类型。
单独分配:例如:
a=3
运行a=3后,变量a就变成了对对象3的引用。在内部,变量实际上是一个指向对象内存空间的指针。
因为Python变量只是对象的引用或者对象的指针,所以变量引用经常可以在程序中改变。
代码如下:
X=42 #变量被绑定到一个整数对象。
X=Hello #现在又是一个字符串了。
X=[1,2,3] #现在又是列表了。
专业表达如下:
*变量是系统表的一个元素,带有连接到对象的空间。
*对象是一个分配的内存块,用于存储它所代表的值。
*引用是从变量到对象自动形成的指针。
*特别说明:类型属于对象,不属于变量。
例如,就像a=3一样,整数对象3包含两种信息。
1.该值为3
2.头消息:告诉Pthyon它是一个整数对象[相当于一个指向int的指针]
分享:例如:
代码如下:
a=3
b=a
运行赋值语句b=a后,变量A和变量B指向同一个对象的内存空间。
从上图可以看出,A和B,id相同,指向同一个integer对象3,或者同一块内存。
如果A被删除,不会影响b。
复制概念的引入是针对可变对象共享引用的潜在副作用。
[可变对象-不可变对象]
在Python中,不可变对象是指一旦创建就不能修改的对象,包括字符串、祖先和数字。
在Python中,可变对象是指可以修改的对象,包括列表和字典。
上面的A和B都是整数。整数是不可变的对象。如果它们是可变对象,那就另当别论了。
代码如下:
L1=[2,3,4]# L1 L1变量指向一个可变对象:一个列表
L2=L1 #将L1值赋给L2后,它们共享并引用同一个列表对象[1,2,3,4]
L1[0]=200 #因为列表是可变的,所以改变L1中第一个元素的值
L1;L2 #发生变化后,L1和L2同时发生变化,因为物体本身的价值发生变化。
[200, 3, 4]
[200, 3, 4]
如果你不想改变列表L2的值,有两种方法:切片和复制模块。
代码如下:
L1=[2,3,4]
L2=L1
id(L1);Id(L2) # Share引用了一个可变对象
45811784L
45811784L
L2=L1[:] #切片操作
id(L1);Id(L2) #切片后,对象就不一样了。
45811784L
45806920L
L1[0]=200
L1;L2 #L1变了,L2没变。
[200, 3, 4]
[2, 3, 4]
[副本]
切片技术适用于所有序列,包括列表、字符串和祖先。
但是切片不能应用于字典。只有D.copy()方法或D.deepcopy()方法可用于字典。
复制,可用于序列或字典。
代码如下:
导入副本
X=copy.copy(Y) # light copy:仅复制顶级对象或父对象。
X=copy.deepcopy(Y) # Deep copy:复制所有对象、顶层对象及其嵌套对象。或者:父对象及其子对象。
如果字典只有顶级对象:
如果对象嵌套在字典中:
[结论]
深度和深度都复制源对象,占用不同的内存空间。
如果源对象只有一个一级目录,则源所做的任何更改都不会影响深拷贝和浅拷贝对象。
如果源对象有多个级别的目录,对源的任何更改都将影响轻型副本,但不会影响深层副本。
序列的切片实际上是一个浅拷贝,即只拷贝顶层对象。
直接赋值:实际上是一个对象的引用(别名)。
复制:复制父对象,但不复制对象的内部子对象。
复制模块的Deepcopy方法完全复制父对象及其子对象。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。