6

可能重复:
Python 列表中的意外功能

我想在 Python 中制作一个列表列表,但显然这不起作用,因为更改一个数字会改变几个。为什么会这样,我该如何解决?

>>> a = [[0]*3]*4
>>> a[0][0] = 1
>>> a
[[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0]]
4

4 回答 4

8

您发现的是一个经典的 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]]
于 2012-10-21T02:07:31.127 回答
4

在 Python 中,[x]*n创建一个包含nx. x如果是不可变的(字符串、元组等),这是非常好的,但是如果x是可变的,它会变得相当混乱,因为对一个元素的更改会影响x,因此似乎会影响列表的所有元素。

因此,解决方案是使用列表推导来创建n新事物:

[x for _ in xrange(n)] # we use _ here as a "dummy variable"

在你的情况下,它看起来像

a = [[0]*3 for _ in xrange(4)]
于 2012-10-21T02:12:04.670 回答
1

不要使用*. 使用列表理解并创建如下:

>>> 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 的答案以获得更好的解释。

于 2012-10-21T02:08:25.790 回答
-1

在列表中使用*时,它会创建副本,因此当您执行a[0][0]=1所有其他子列表的复制时。

为了解决这个问题,请使用生成器表达式来创建您的列表。

于 2012-10-21T02:07:40.150 回答