6

假设我想用全 0 初始化一个 2D Python 列表,我会这样做:

test = [[0.0] * 10] * 10

然后我开始修改第一个列表中的值......

test[0][0] = 1.0

但由于某种原因,这会影响 ALL 列表的第一项:

print test

[[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]

这是怎么回事?为什么它制作内部列表的深层副本,但外部列表的浅层副本?

4

2 回答 2

6

这样做 [[0.0] * 10] * 10实际上会创建同一列表的多个副本,因此修改一个将影响所有副本:

>>> test = [[0.0] * 10] * 10
>>> [id(x) for x in test]     #see all IDs are same
[3065020524L, 3065020524L, 3065020524L, 3065020524L, 3065020524L, 3065020524L, 3065020524L, 3065020524L, 3065020524L, 3065020524L]

试试这个:

>>> test = [[0.0]*10 for _ in xrange(10)]
>>> test[0][0] = 1.0
>>> test
[[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]

整数/浮点数是不可变的,而列表是可变的:

>>> x = y = []
>>> x is y       # Both point to the same object
True 
>>> x.append(1)  # list.extend modifies a list in-place
>>> x,y          # both references to [] can see the modification
([1], [1])
>>> x = y = 1
>>> x is y      #both points to the same object
True
>>> x+=1        # only x gets modified, it now points to a new object 2
>>> x,y         # y still points to the same object 1
(2, 1)
于 2013-06-13T23:59:33.270 回答
3

该列表test包含同一列表的多次迭代,因此其中一个的更改(正如您通过重新分配 的第一个元素所做的那样test[0])反映在所有其他列表中。试试这个:

[[0.0]*10 for _ in xrange(10)]  # or `range` in Python 3.x

当然,如果你只有 ,你就不必担心这一点[0.0] * 10,因为这会创建一个整数列表,其中任何一个都不会发生变异。另一方面,列表确实是可变的。

于 2013-06-14T00:00:03.173 回答