关于浅拷贝,深拷贝

浅拷贝:字符串被显示的拷贝,列表元素的引用被拷贝(如果被拷贝的是列表,那么浅拷贝后,拷贝出来的列表的id和被拷贝的列表的id是不同的,说明是两个对象,但是如果是x = p的形式的话,所有东西包括整个列表的id都是一样的),因此修改例如字符串这种不可变的值,不会在被拷贝的对象中有改变。

深拷贝:字符串被显示的拷贝,列表被完全拷贝(创建了一个新对象,内容和之前的列表一致)。

不管是浅拷贝还是深拷贝,被拷贝的字符串这种不可变的值一开始的id都是一样的,不管是深浅都是新建了一个对象,而不是像引用赋值那样只是多加了一个对对象的引用。

下面用id()函数来说明这种变化。

>>> p = ['name', ['saving', 100]]
>>> h = p[:]
>>> [id(x) for x in p, h]
[4490260704, 4490336016]

浅拷贝的两个对象id不同,说明是两个对象。但是如果只是增加了一个对对象的引用,那么id就完全一样。

>>> p
['name', ['saving', 100]]
>>> x = p
>>> [id(x) for x in p, x]
[4490260704, 4490260704]

接着说重点,浅拷贝的两个对象本身的id就不同,然后我们看其中的元素,经测试,没被修改的浅拷贝中的不可变元素(name)id一致,这里我们不探讨这个,重点在后面的list,看看二者的id知否一致。

>>> p
['name', ['saving', 100]]
>>> h
['name', ['saving', 100]]
>>> [id(x[1]) for x in p, h]
[4490174336, 4490174336]

我们再试试深拷贝。

>>> p
['name', ['saving', 100]]
>>> import copy
>>> w = copy.deepcopy(p)
>>> [id(x[1]) for x in p, h, w]
[4490174336, 4490174336, 4490337744]

我们可以发现,深拷贝的list的id却是变了,说明是完全新建了一个list对象。

我们再试试不可变元素。

>>> p
['name', ['saving', 100]]
>>> h
['name', ['saving', 100]]
>>> [id(x[0]) for x in p, h]
[4489215600, 4489215600]
>>> h[0] = 'hs'
>>> [id(x[0]) for x in p, h]
[4489215600, 4490618080]

id不同,说明现在name处的string是完全两个元素了。

下面试一下元组,如果元组中的元素只包含不可变对象,那么对他进行深拷贝会发生什么。

>>> p
['name', ('saving', 100)]
>>> w = copy.deepcopy(p)
>>> [id(x[1]) for x in p, w]
[4490184464, 4490184464]

可以发现,如果元组中的元素都是不可变类型,那么对元组进行深拷贝也是浅拷贝。

我们再试下如果元组中包含list的情况。

>>> p
['name', ('saving', [100])]
>>> w = p[:]
>>> del w
>>> w = copy.deepcopy(p)
>>> [id(x[1]) for x in p, w]
[4490184392, 4490181520]

如果元组中包含可变对象,那么深拷贝对元组的深拷贝就是起作用。

总结:浅拷贝拷贝的是可变对象的引用,真正的深拷贝是新建了一个对象,内容跟原来的一致。

posted on 2015-08-12 17:54  sudo987  阅读(125)  评论(0编辑  收藏  举报

导航