如何深拷贝一个列表?

新手上路,请多包涵

After E0_copy = list(E0) , I guess E0_copy is a deep copy of E0 since id(E0) is not equal to id(E0_copy) .然后我在循环中修改了 E0_copy ,但是为什么之后 E0 不一样呢?

 E0 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
for k in range(3):
    E0_copy = list(E0)
    E0_copy[k][k] = 0
    #print(E0_copy)
print E0  # -> [[0, 2, 3], [4, 0, 6], [7, 8, 0]]

原文由 Shen 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 593
2 个回答

E0_copy 不是深拷贝。您不会使用 list() 进行深层复制。 ( list(...)testList[:] 都是浅拷贝。)

您使用 copy.deepcopy(...) 深度复制列表。

 deepcopy(x, memo=None, _nil=[])
    Deep copy operation on arbitrary Python objects.

请参阅以下片段 -

 >>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = list(a)
>>> a
[[1, 2, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a[0][1] = 10
>>> a
[[1, 10, 3], [4, 5, 6]]
>>> b   # b changes too -> Not a deepcopy.
[[1, 10, 3], [4, 5, 6]]

现在看到 deepcopy 操作

>>> import copy
>>> b = copy.deepcopy(a)
>>> a
[[1, 10, 3], [4, 5, 6]]
>>> b
[[1, 10, 3], [4, 5, 6]]
>>> a[0][1] = 9
>>> a
[[1, 9, 3], [4, 5, 6]]
>>> b    # b doesn't change -> Deep Copy
[[1, 10, 3], [4, 5, 6]]

解释一下, list(...) 不会递归地复制内部对象。它只复制最外层列表,同时仍然引用相同的内部列表,因此,当您改变内部列表时,更改会反映在原始列表和浅表副本中。通过检查 id(a[0]) == id(b[0]) where b = list(a) 可以看到浅复制引用了内部列表。

原文由 Sukrit Kalra 发布,翻译遵循 CC BY-SA 4.0 许可协议

在 Python 中,有一个名为 copy 的模块具有两个有用的功能:

 import copy
copy.copy()
copy.deepcopy()

copy() 是一个浅拷贝函数。如果给定的参数是一个复合数据结构,例如一个 list ,那么 Python 将创建另一个相同类型的对象(在本例中是一个 新的 list ),但对于旧列表中的所有内容,只复制它们的引用。可以这样想:

 newList = [elem for elem in oldlist]

直觉上,我们可以假设 deepcopy() 将遵循相同的范式,唯一的区别是对于每个 elem 我们将递归调用 deepcopy ,(就像 mbguy 的回答

但这是错误的!

deepcopy() 实际上保留了原始复合数据的图形结构:

 a = [1,2]
b = [a,a] # there's only 1 object a
c = deepcopy(b)

# check the result
c[0] is a # False, a new object a_1 is created
c[0] is c[1] # True, c is [a_1, a_1] not [a_1, a_2]

这是棘手的部分:在 deepcopy() 的过程中,哈希表(Python 中的字典)用于将每个旧对象 ref 映射到每个新对象 ref,这防止了不必要的重复,从而保留了结构复制的复合数据。

官方文档

原文由 watashiSHUN 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题