万物之中, 希望至美.

Python中的浅拷贝与深拷贝

2018.01.25

在面试过程中,经常会被问浅拷贝与深拷贝的区别。所以,在这里记录一下自己的理解,以便以后好复习。

浅拷贝(shallow copy)

所谓“浅拷贝”,是指在复制一个对象时,构建一个新的对象,并将原对象中发现的引用插入到该对象中.

浅拷贝的实现方式常见的有:工厂函数、切片操作、copy模块中的copy函数等 实现如下:

>>> a = [1, 2, [3, 4]]
>>> b = a[:]
>>> id(a)
4505384008
>>> id(b)
4504586056

>>> [id(x) for x in a]
[4470102640, 4470102672, 4505384072]
>>> [id(x) for x in b]
[4470102640, 4470102672, 4505384072]

>>> a[2] += [5]
>>> a
[1, 2, [3, 4, 5]]
>>> b
[1, 2, [3, 4, 5]]

从上面可以看出,a和b指向内存中不同的list对象,但它们的元素却指向相同的对象,此时操作 a 中的元素,b 中的元素也会跟着一起改变。

深拷贝(deep copy)

所谓“深拷贝”,是指在复制一个对象时,也构建一个新的对象,但是在遇到引用会继续递归拷贝其所指向的具体内容,也就是说构建出来的新的对象不会收到其他引用对象操作的影响。

深拷贝的实现方式:使用copy模块中的deepcopy()函数

>>> import copy
>>> a = [1, 2, [3, 4]]
>>> b = copy.deepcopy(a)
>>> id(a)
4424991880
>>> id(b)
4424991688
>>> [id(x) for x in a]
[4416637552, 4416637584, 4424992072]
>>> [id(x) for x in b]
[4416637552, 4416637584, 4424991752]

>>> a[2] += [5]
>>> print(a)
[1, 2, [3, 4, 5]]
>>> print(b)
[1, 2, [3, 4]]

这里可能会产生一个疑惑,为什么使用了深拷贝,a 和 b 中的元素有些还是一样呢?

这是因为对于不可变对象,当需要一个新的对象时,python可能会返回已经存在的某个类型和值都一致的对象的引用。而且这种机制并不会影响 a 和 b 的相互独立性,因为当两个元素指向同一个不可变对象时,对其中一个赋值不会影响另外一个。

comments powered by Disqus