深拷贝和浅拷贝Python,python中深拷贝和浅拷贝
Python深拷贝定义(deepcopy)中复制、深层复制和浅层复制的区别
在Python中,因为一切都是对象,所以可以引用任何变量,也就是可以赋给任何变量。然而,在Python中,变量赋值是有区别的。一般来说,Python中的变量赋值都是浅拷贝。如果需要使用深层副本,则需要指定它们。
深层复制是对原始对象的“复制和粘贴”。实际上,它会在内存中重新打开一个新的内存空间来存储这些数据。两个变量其实是两个不同的变量,只是数据值相同,两个变量的运算不会互相影响。
浅拷贝(copy)
在Python中进行浅拷贝数据时,如果浅拷贝的数据是Python中的原子数据结构,比如str、int、float、tuple等不可变的原子数据结构,那么在Python解释器中会为新赋值的变量打开一个新的内存空间,新的内存空间中存储的值与浅拷贝数据的值一致。
例如:
此时需要注意的是,如果Python中int的值小于某个数,Python仍然会引用相同的数据值,即变量A和B的地址是相同的。比如:
而当改变A和B的值时,地址也会改变,也就是说A和B都是指向存储值的特定地址空间的指针。如果修改后A和B的值相同,那么A和B的地址也将相同。比如:
在对一些可变对象进行浅层复制时,实际上是对可变对象的二级引用,并没有开辟新的内存空间。比如:
从图中可以看出,A和B都指的是列表。虽然A首先引用的是list,但是它们在内存中的地址是相同的,这意味着它们实际上是同一个list的两个不同的昵称。
列表、“=”和切片运算两种不同的赋值方法,它们之间的区别如下:
“=”:对于浅拷贝,这个符号实际上是将“=”两边两个不同的变量同时指向同一个内存空间,内存空间的值是相同的。当一个变量修改了内存空间中的值,用另一个变量引用内存空间中的变量时,值也会发生变化,因为它们都指向同一个数据值。
切片操作:切片操作(a[start_index:end_index])给另一个变量赋值时,不再是两个不同的变量同时指向一个内存地址空间中的数据值。因为切片操作会返回一个新的列表,新的变量会收到一个新的列表,新列表中的数据值是切片后的数据值,内存中的地址空间是不同的。如图所示:
此时对C的任何操作都与a(b)无关,因为A和B实际上是同一个链表。
但是当列表中有可变数据结构时(list,dict等)就会出现不一样的结果,因为在Python中,对于可变的数据类型,Python解释器会给变量采用引用的方式对 可变的数据类型的数据 进行引用,为了节省内存空间。 如图所示:
如果需要两个变量同时独立操作链表(链表中有变量数据类型的数据),那么就需要使用深度复制直接复制数据而不是引用。这时需要使用Python中的copy函数,copy库中的deepcopy()方法可以直接复制(深度复制)数据,如图:
从图中可以看出,C是A的深度副本,B是A的切片操作的浅层副本,同时修改了列表中的变量元素,说明C中的数据存储在一个独立的内存空间中。
在Python对数据对象进行拷贝时,需要注意:
首先,非容器类型(如数字、字符串和其他“原子”对象,如代码、类型和范围对象)没有被复制。浅拷贝是通过全切片完成的。
第二,如果元组变量仅包含原子类型对象,则不会对它们进行深度复制。
从图中可以看出,元组都是“原子”类型的数据对象。此时,它们被深度复制,但是查看内存中的地址并没有为B开辟新的内存空间,这一点需要注意。
但是,如果tuple具有可变数据类型的对象,深度复制将会工作。
-
如果你觉得我的博客对你有帮助,请给我一点鼓励。你们的鼓励是对我最大的肯定,我会继续努力。谢谢你。
支付宝:微信支付:
贴@ 2018-10-15 23:16东京樱花飘下巴黎阅读(.)评论(.)编辑收藏
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。