1

我使用python的*创建了一个默认值为0的二维列表[[0]*10]*10。但是当我将第一个元素设置为1时,第一个列的所有元素恰好是1,为什么?

当我使用附加创建列表时不会发生这种情况(请参阅下面的变量数据)。

#!/bin/env python
#encoding=utf8

width = 10
height = 10

data = []
for i in xrange(width):
    data.append([0 for j in xrange(height)])

data2 = [[0]*width]*height

print "before:",data == data2
data[0][0] = 1
data2[0][0] = 1
print "after:",data == data2

print "actually:"
print data
print data2

输出:

before: True
after: False
actually:
[[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]]
[[1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
4

2 回答 2

1

列表上的*操作员将重复列表中的对象。但它不会复制对象,它会重复实际对象本身。

区别很微妙,很多时候你不会注意到它。如果对象是不可变的,例如数字或字符串,您所能做的就是将对象替换为不同的对象,然后列表的成员将不再是同一个对象。

当列表中的对象可以修改时,例如另一个列表,对该对象的任何修改都会反映在列表中的所有其他重复引用中。

有一个尴尬的解决方法:

data3 = [[0]*width for i in range(height)]
于 2013-06-04T18:09:18.000 回答
0

这里:

[[0]*width]

您只创建一个 list [0],然后创建另一个包含width对该单个对象的引用的列表。关键是*运算符只计算一次它的操作数。

这里:

for i in xrange(width):
    data.append([0 for j in xrange(height)])

您正在为每个迭代创建一个新列表,然后追加。

于 2013-06-04T18:01:09.307 回答