由列表乘法创建的嵌套引用列表的Deepcopy不起作用

Gon*_*nzo 4 python nested list multiplication deep-copy

尽管我喜欢Python,但引用和深度复制的东西有时会让我感到厌烦.

为什么deepcopy在这里不起作用:

>>> import copy
>>> a = 2*[2*[0]]
>>> a
[[0, 0], [0, 0]]
>>> b = copy.deepcopy(a)
>>> b[0][0] = 1
>>> b
[[1, 0], [1, 0]]     #should be: [[1, 0], [0, 1]]
>>> 
Run Code Online (Sandbox Code Playgroud)

我正在使用一个numpy数组作为一个workarround,无论如何我以后需要.但我真的希望如果我使用deepcopy,我就不必再追逐任何非预期的引用了.是否有更多的陷阱不起作用?

Mar*_*ers 13

它不起作用,因为您正在创建一个包含对同一数组的两个引用的数组.

另一种方法是:

[[0]*2 for i in range(2)]
Run Code Online (Sandbox Code Playgroud)

或者更明确:

[[0 for j in range(2)] for i in range(2)]
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为它在每次迭代时创建一个新数组.

是否有更多的陷阱不起作用?

每当你有一个包含引用的数组时,你应该小心.例如[Foo()] * 2不一样[Foo() for i in range(2)].在第一种情况下,只构造了一个对象,并且该数组包含两个对象.在第二种情况下,构造了两个单独的对象.


Ros*_*ron 7

它完全按照您的预期工作.

a = 2*[2*[0]]

乘以[[0,0]]2 *,新列表的两个元素都将指向SAME [0,0]列表.a[0]并且a[1]是相同的列表,因为复制了引用,而不是数据(这是不可能的).更改其中一个元素的第一个元素会改变另一个元素的第一个元素.

copy.deepcopy 正确复制列表,保留唯一对象.