码农都知道,在面向对象中,对象的复制有深浅之分。在 Python 中,一切皆对象,无论你把对象作为参数传递还是作为返回值,传递的都是引用,也就是浅复制。那么,深复制呢?

在标准库中,copy 模块有两个方法,分别是 copydeepcopy。以 list 对象举例:


in[0]:

import copy

list1 = [1, 2, 3]
new_list1 = list1
new_list2 = copy.copy(list1)
new_list3 = copy.deepcopy(list1)

print list1
print new_list1
print new_list2
print new_list3

执行以上操作,输出为:


out[0]:

[1, 2, 3]
[1, 2, 3]
[1, 2, 3]
[1, 2, 3]

在上例中,list1 和 new_list1 实际指向同一对象,证据如下:


in[1]:

list1[0] = 4
print list1
print new_list1
print new_list2
print new_list3

out[1]:

[4, 2, 3]
[4, 2, 3]
[1, 2, 3]
[1, 2, 3]

那 copy 和 deepcopy 的区别在哪儿?继续看例子


in[2]:
	
import copy

list1 = [[1, 2], [3, 4], [5, 6]]
new_list1 = copy.copy(list1)
new_list2 = copy.deepcopy(list1)

print list1
print new_list1
print new_list2

list1[0].append(8)

print list1
print new_list1
print new_list2

out[2]:

[[1, 2], [3, 4], [5, 6]]
[[1, 2], [3, 4], [5, 6]]
[[1, 2], [3, 4], [5, 6]]
[[1, 2, 8], [3, 4], [5, 6]]
[[1, 2, 8], [3, 4], [5, 6]]
[[1, 2], [3, 4], [5, 6]]

由上例可见 new_list1 和 new_list2 的引用已经不同于但是其属性的引用就不同了,使用 copy 方法复制出的 new_list1 的属性 new_list[0] 仍然同 list1 共享引用,而使用 deepcopy 方法复制出的 new_list2 副本则不是。

也就是说,如果你想把对象中的属性也被复制,就得使用 deepcopy 方法。