copy 模块
浅拷贝的局限性 (Limitation of Shallow Copy)
copy()
方法不会递归地创建子对象的副本,因此如果子对象是可变的(例如嵌套列表),对子对象的任何修改都会反映在父对象和其副本中。
python
>>> old_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
#将旧列表复制到新列表 (浅拷贝)
>>> new_list = old_list.copy()
#检查两个列表是否指向同一个对象 (False,列表本身是新的)
>>> id(new_list)==id(old_list)
False
#检查两个列表的项是否指向相同的对象 (True,子列表是共享的)
>>> [id(new_list[idx])==id(old_list[idx]) for idx in range(len(old_list))]
[True, True, True]
#修改新列表的子列表
>>> new_list[1][1] = 0
>>> new_list
[[1, 2, 3], [4, 0, 6], [7, 8, 9]]
>>> old_list # old_list 也被修改了
[[1, 2, 3], [4, 0, 6], [7, 8, 9]]
正如我们在输出中看到的,修改了 new_list[1][1]
,这同时反映在 new_list
和 old_list
中。
copy
模块提供了 deepcopy()
函数,有助于缓解此问题。
深拷贝 - deepcopy(x[, memo]) (Deep Copy - deepcopy(x[, memo]))
深拷贝克服了 copy()
的缺点,并递归地创建原始列表中找到的子对象的副本。这导致创建了原始对象的独立副本。
python
>>> import copy
>>> old_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
#将旧列表深拷贝到新列表
>>> new_list = copy.deepcopy(old_list)
#检查两个列表是否指向同一个对象 (False)
>>> id(new_list)==id(old_list)
False
#检查两个列表的项是否指向相同的对象 (False,子列表也是新的)
>>> [id(new_list[idx])==id(old_list[idx]) for idx in range(len(old_list))]
[False, False, False]
#修改新列表的子列表
>>> new_list[1][1] = 0
>>> new_list
[[1, 2, 3], [4, 0, 6], [7, 8, 9]]
>>> old_list # old_list 未被修改
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
注意子项的 id()
相等性从 [True, True, True]
变为 [False, False, False]
。正如我们在输出中看到的,修改了 new_list[1][1]
,这仅反映在 new_list
中。