您的位置:首页 > 其它

浅拷贝和深拷贝详解

2016-04-21 00:25 232 查看
官方文档:

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.

在python中,对象赋值实际上是对象的引用。

浅拷贝: 拷贝对象的值,但不拷贝对象内部元素的值,只拷贝内部元素的引用

>>> SL = {'name': 'SL',  'friend': ['A', 'B', 'C']}
>>> YS = SL.copy()


查看SL,YS的id值

>>> print id(SL), id(YS)
139783840481360 139783840476248


可以看出,两者的id值是不同的,说明拷贝对象的值。

接下来查看SL[‘name’],YS[‘name’] 以及 SL[‘friend’],YL[‘friend’]的id值。

>>> print id(SL['name']), id(YS['name'])
139783840488224 139783840488224
>>> print id(SL['friend']), id(YS['friend'])
139783840438608 139783840438608


内部元素的id值分别对应相同,说明都是指向相同对象。

下面对SL作出修改,然后查看SL和YS的状态

>>> SL['name'] = 'SS'
>>> SL['friend'][0] = 'Z'
>>> SL
{'name': 'SS', 'friend': ['Z', 'B', 'C']}
>>> YS
{'name': 'SL', 'friend': ['Z', 'B', 'C']}


SL[‘name’]指向字符串(不可变对象),SL[‘friend’]指向是列表(可变对象)。

可以看出,在替换SL中的不可变对象时,YS不受影响,修改SL中的可变对象时,YS也会相应改变。

分析:

SL[‘name’],YS[‘name’]原本指向相同对象,由于SL[‘name’]指向的是不可变对象。所以当改变SL[‘name’]时,会创建一个新的字符串对象,并使SL[‘name’]指向它,YS[‘name’]仍然指向原本对象。

SL[‘frined’],YS[‘friend’]指向相同对象(即列表),属于可变对象。因而修改SL[‘friend’]时,不需要创建新对象,直接修改SL[‘friend’]指向的列表。

查看一下改变之后SL[‘name’],YS[‘name’]和SL[‘friend’],YS[‘friend’]的id值

>>> print id(SL['name']), id(YS['name'])
139783774899256 139783840488224
>>> print id(SL['friend']), id(YS['friend'])
139783840438608 139783840438608


前两者的id值已经不同,后两者的id值相同,由此可见,上述分析是正确的。

因此,浅拷贝会得到一个新的对象,但对于对象内部的元素,无论是可变对象还是不可变对象都只拷贝引用

深拷贝: 拷贝对象的值,拷贝不可变元素的引用,拷贝可变元素的值

>>> SL = {'name': 'SL',  'friend': ['A', 'B', 'C']}
>>> YS = deepcopy(SL)


查看SL,YS的id值

>>> print id(SL), id(YS)
139732549292672 139732549294912


两者的id值不同,说明拷贝对象的值。接下来查看SL[‘name’],YS[‘name’] 以及 SL[‘friend’],YL[‘friend’]的id值。

>>> print id(SL['name']), id(YS['name'])
139732549298976 139732549298976
>>> print id(SL['friend']), id(YS['friend'])
139732549249360 139732549249216


前两者的id值相同,后两者的id值不同。这里也对SL作出修改,然后查看SL和YS的值

>>> SL['name'] = 'SS'
>>> SL['friend'][0] = 'Z'
>>> SL
{'name': 'SS', 'friend': ['Z', 'B', 'C']}
>>> YS
{'name': 'SL', 'friend': ['A', 'B', 'C']}


不管对SL作出怎么的修改都不会影响到YS的值

分析:

修改SL[‘name’]时,同上

SL[‘frined’],YS[‘friend’]原本就指向不同对象,修改SL[‘friend’]时,明显不会影响到YS的值。

下面查看一下改变之后SL[‘name’],YS[‘name’]和SL[‘friend’],YS[‘friend’]的id值

>>> print id(SL['name']), id(YS['name'])
139732549296616 139732549298976
>>> print id(SL['friend']), id(YS['friend'])
139732549249360 139732549249216


意料之中,仍然对应不相同

因此,深拷贝也会得到一个新的对象,对于对象的内部元素,拷贝不可变对象的引用,拷贝可变对象的值

总而言之,浅拷贝得到的副本,修改副本内部的可变对象时会影响到原始对象;深拷贝得到的副本 ,无论如何修改副本都不会影响到原始对象。

注:浅拷贝和深拷贝只有在关于复合对象(包含其它对象的对象,列表,类等)才有区别。对于不可变对象,没有被拷贝的说法,即使用deepcopy,查看id值也是一样的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: