尽管我喜欢Python,但引用和深度复制的东西有时会让我感到厌烦。
为什么深度复制在这里不起作用:
>>> 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]]
>>>
我正在使用一个numpy数组作为一个workarround,无论如何我以后需要。但我真的希望如果我使用deepcopy,我就不必再追逐任何非预期的引用了。是否有更多陷阱不起作用?
答案 0 :(得分:13)
它不起作用,因为您正在创建一个包含对同一数组的两个引用的数组。
另一种方法是:
[[0]*2 for i in range(2)]
或者更明确:
[[0 for j in range(2)] for i in range(2)]
这是有效的,因为它在每次迭代时都会创建一个新数组。
是否有更多陷阱不起作用?
每当你有一个包含引用的数组时,你应该小心。例如,[Foo()] * 2
与[Foo() for i in range(2)]
不同。在第一种情况下,只构造了一个对象,并且该数组包含两个对象。在第二种情况下,构造了两个独立的对象。
答案 1 :(得分:7)
它完全按照您的预期运作。
a = 2 * [2 * [0]]
当您将[[0,0]]
与2 *
相乘时,新列表的两个元素都将指向SAME [0,0]
列表。 a[0]
和a[1]
是相同的列表,因为复制了引用,而不是数据(这是不可能的)。更改其中一个元素的第一个元素会改变另一个元素的第一个元素。
copy.deepcopy
正确复制列表,保留唯一对象。