时间:2021-05-22
直接赋值: 对象的引用,也就是给对象起别名
浅拷贝: 拷贝父对象,但是不会拷贝对象的内部的子对象。
深拷贝: 拷贝父对象. 以及其内部的子对象
在之前的文章中,提到可变对象和不可变对象,接下来也是以这两者的区别进行展开
直接赋值
对于可变对象和不可变对象,将一个变量直接赋值给另外一个变量,两者 id 值一致,其实本质上是将变量量绑定到对象的过程.
>>> a=1>>> b=a>>> id(a) == id(b)True>>> c="string">>> d=c>>> id(c) == id(d)True>>> e=[1,2,3]>>> f=e>>> id(e)==id(f)True关于修改新变量的值,对原有变量会产生的影响,在可变对象和不可变对象 中也做了讲述,这里通过几个例子,重新温习一下
不可变对象
>>> x=1>>> y=x>>> id(x)==id(y)True>>> id(1)==id(y)True>>>>>> id(x)1500143776>>> y=y+1>>> y2>>> x1>>> id(x)==id(y)False>>> id(y)1500143808>>> id(x)1500143776对于不可变对象,修改赋值后的新变量,不会对原有变量造成任何影响.为什么出现这种现象呢?因为不可变对象一旦创建之后就不允许被改变.后面对 y 进行的操作,其实是重新创建一个对象并绑定的结果:
可变对象
>>> m=[1,2,3]>>> n=m>>> id(n)==id(m)True>>> id(m)1772066764488>>> id(n[0])1772066764656>>> n[0]=4>>> n[4, 2, 3]>>> m[4, 2, 3]>>> id(n)==id(m)True>>> id(m)1772066764488对于可变对象,修改赋值后的变量,会对原有的变量造成影响,会导致其 value 值的改变,但是其id 值保持不变
从上图不难看出,这个时候的 id(n[0]) 的值,和未修改前的 id值应该不一样,可以输出看一下
>>>id(n[0])1772066764752 # 最初没有修改前是 1772066764656n[0] 修改前后为什么 id 值出现改变呢? 首先需要明确一点 n[0] 绑定的是一个不可变对象,在文章的最初提到,不可变对象一旦创建就不允许修改.显然对 n[0] 进行修改,不能在绑定对象的内存上进行修改,那如何实现重新赋值呢?只能创建一个新的对象 4 ,然后将 n[0] 绑定到新的对象
浅拷贝和深拷贝
先看一下官方文档的定义
The difference between shallow and deep copying is only relevant for compound objects (objects that contain other objects, like lists or
class instances).
A shallow copy constructs a new compound object and then (to the
extent possible) inserts the same objects into it that the
original contains.
A deep copy constructs a new compound object and then, recursively,inserts copies into it of the objects found in the original.
从文档中不难看出,上面提到深拷贝和浅拷贝两者区别在于在复合对象,那接下来也只讨论复合对象.
浅拷贝
注意到官方文档也提到对浅拷贝和深拷贝的定义,从上文中不难看出,浅拷贝构建一个复合对象,然后将原有复合对象包含的对象插入到新的复合对象中
从上图不难看出,浅拷贝后,新复合对象包含的对象(可变或者不可变)的 id 值和原有对象包含的对象的 id 值相同
看一下具体例子:
>>> import copy>>> a=[1,2,[3,4]]>>> b=copy.copy(a)>>> id(b[0])==id(a[0])True>>> id(b[2])==id(a[2])True>>> id(b[2][0])==id(a[2][0])True现在让我们试着修改一下浅拷贝后的 b 的值,在修改前,可以先思考一下,如果修改 b[0] 可能会发生什么?
由于 b[0] = 1,很显然 1 属于不可变对象,那么根据对不可变变量修改的规则,则 b[0] 会绑定到新的变量上,而 a[0] 的由于没有修改,则保持不变,真的是这样吗?让我们验证一下
>>> b[0]=5>>> b[5, 2, [3, 4]]>>> a[1, 2, [3, 4]]接下来我们要尝试修改一下 b[2],由于 b[2] 绑定的对象是 list,属于可变对象,按照上面说的可变对象修改的规则,则修改后的 b[2] 的 id 值保持不变,但是其 value 值会发生改变. 同样的让我们通过例子验证一下
>>> id(b[2])4300618568>>> b[2][0]=6>>> id(b[2])4300618568>>> b[5, 2, [6, 4]]>>> a[1, 2, [6, 4]]由于 b[2] 和 a[2] 绑定同一个可变对象,很显然对 b[2] 的修改同样会映射到 a[2] 上
深拷贝
深拷贝构建一个复合对象,然后递归的将原有复合包含的对象的副本插入到新的复合对象中
若上图所示,深拷贝后,新的复合对象包含的对象,若对象为不可变对象,则 id 值保持不变,若对象为可变对象,则 id 值发生改变
看一个例子:
>>> import copy>>> a=[1,2,[3,4]]>>> b=copy.deepcopy(a)>>> id(b[0])==id(a[0])True>>> id(b[2])==id(a[0])False>>> id(b[2][0])==id(a[2][0])True接下来让我们修改一下变量 b,这里就不在修改不可变对象 b[0] 和 b[1] 了,因为结果很明显,对 a 不会产生任何影响,我们来修改 b[2],那么修改 b[2] 会对 a[2] 产生影响吗?很明显答案是不会,因为深拷贝就相当于克隆出了一个全新的个体,两者不再有任何关系
>>> b[2][0]=5>>> b[1, 2, [5, 4]]>>> a[1, 2, [3, 4]]以上就是详解Python直接赋值,深拷贝和浅拷贝的详细内容,更多关于Python直接赋值,深拷贝和浅拷贝的资料请关注其它相关文章!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
python深拷贝和浅拷贝的区别是: 1、直接赋值,默认浅拷贝传递对象的引用而已,原始列表改变,被赋值的b也会做相同的改变。 2、copy浅拷贝,没有拷贝子
Python基础教程之浅拷贝和深拷贝实例详解网上关于Python的深拷贝和浅拷贝的文章很多,这里对三种拷贝进行比较并附实例,大家可以参考下一般的复制#encod
直接赋值和copy的区别:直接赋值:其实就是对象的引用(别名)。浅拷贝(copy):拷贝父对象,不会拷贝对象的内部的子对象。深拷贝(deepcopy):copy
本文实例讲述了Python直接赋值、浅拷贝与深度拷贝。分享给大家供大家参考,具体如下:直接赋值:其实就是对象的引用(别名)。浅拷贝(copy):拷贝父对象,不会
本文实例讲述了JS赋值、浅拷贝和深拷贝(数组和对象的深浅拷贝)。分享给大家供大家参考,具体如下:深拷贝和浅拷贝是只针对Object和Array这样的引用数据类型