我使用python的*创建一个2-dimetion列表[[0] * 10] * 10,默认值为0。 但是当我将第一个元素设置为1时,第一个列的所有元素都发生了1,为什么?
使用append创建列表时不会发生这种情况(参见下面的变量数据)。
#!/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]]
答案 0 :(得分:1)
列表中的*
运算符将重复列表中的对象。但它不会创建对象的副本,它会重复实际的对象本身。
区别是微妙的,很多时候你不会注意到它。如果对象是不可变的,例如数字或字符串,那么您所能做的就是用不同的对象替换对象,然后列表的成员将不再是同一个对象。
当列表中的对象可以被修改时,例如另一个列表,对该对象的任何修改都会反映在列表中的所有其他重复引用中。
有一个尴尬的解决方法:
data3 = [[0]*width for i in range(height)]
答案 1 :(得分:0)
下面:
[[0]*width]
您只创建一个列表[0]
,然后创建另一个列表,其中包含对该单个对象的width
个引用。关键是*
运算符只评估其操作数一次。
这里:
for i in xrange(width):
data.append([0 for j in xrange(height)])
您正在为每个迭代创建一个新列表,然后添加该列表。