可能重复:
Python 列表中的意外功能
我想在 Python 中制作一个列表列表,但显然这不起作用,因为更改一个数字会改变几个。为什么会这样,我该如何解决?
>>> a = [[0]*3]*4
>>> a[0][0] = 1
>>> a
[[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0]]
可能重复:
Python 列表中的意外功能
我想在 Python 中制作一个列表列表,但显然这不起作用,因为更改一个数字会改变几个。为什么会这样,我该如何解决?
>>> a = [[0]*3]*4
>>> a[0][0] = 1
>>> a
[[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0]]
您发现的是一个经典的 Python 陷阱。
x = [0]*3
是一个列表。那里没问题,但[x]*4
会创建一个包含 4 个对完全相同 list 的引用的列表x
。因此,修改第一个元素 ,x
也会修改其他元素。
相反,如果你这样做:
In [193]: a = [[0]*3 for i in range(4)]
然后您会在列表中获得 4 个不同的项目:
In [194]: a[0][0] = 1
In [195]: a
Out[195]: [[1, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
在 Python 中,[x]*n
创建一个包含n
对x
. x
如果是不可变的(字符串、元组等),这是非常好的,但是如果x
是可变的,它会变得相当混乱,因为对一个元素的更改会影响x
,因此似乎会影响列表的所有元素。
因此,解决方案是使用列表推导来创建n
新事物:
[x for _ in xrange(n)] # we use _ here as a "dummy variable"
在你的情况下,它看起来像
a = [[0]*3 for _ in xrange(4)]
不要使用*
. 使用列表理解并创建如下:
>>> a = [[0 for i in range(3)] for j in range(4)]
>>> a[0][0] = 1
>>> a
[[1, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
请参阅 unutbu 和 nneonneo 的答案以获得更好的解释。
在列表中使用*
时,它会创建副本,因此当您执行a[0][0]=1
所有其他子列表的复制时。
为了解决这个问题,请使用生成器表达式来创建您的列表。