浅拷贝
创建一个新的列表对象,其元素仍然是对原列表中元素的引用。
(不存在 “第一层是深拷贝,复制第一层的值;第二层引用对象”,很多帖子的这个说法是错误的)
import copy
a = [[1,2], 2]
b = a.copy()
print(a)
print(b)
print(id(a[0]), ' ', id(a[1]))
print(id(b[0]), ' ', id(b[1]))
输出:
[[1, 2], 2]
[[1, 2], 2]
139652119530752 139652121934160
139652119530752 139652121934160
可以看到无论是嵌套的第二层列表还是第一层元素的id都是相同的。
如下造成许多人的错觉:
import copy
a = [[1,2], 2]
b = a.copy()
print(a)
print(b)
print(id(a[0]), ' ', id(a[1]))
print(id(b[0]), ' ', id(b[1]))
a[0][0] = 22
a[1] = 10
print(a)
print(b)
print(id(a[0]), ' ', id(a[1]))
print(id(b[0]), ' ', id(b[1]))
输出:
[[1, 2], 2]
[[1, 2], 2]
140026856955008 140026859350352
140026856955008 140026859350352
[[22, 2], 10]
[[22, 2], 2]
140026856955008 140026859350608
140026856955008 140026859350352
是因为忽略了数字类型是不可变类型,对于不可变类型(如整数、字符串、元组等),赋值操作总是创建一个新的对象,而不是复制现有对象。嵌套的列表是可变类型,它的内存是不变的。
深拷贝
创造一个新的对象,深拷贝不复制引用,开辟单独的内存地址。copy.deepcopy()