1

当我定义一个列表并尝试像这样更改单个项目时:

list_of_lists = [['a', 'a', 'a'], ['a', 'a', 'a'], ['a', 'a', 'a']]
list_of_lists[1][1] = 'b'
for row in list_of_lists:
    print row

它按预期工作。但是当我尝试使用列表理解来创建列表时:

row = ['a' for range in xrange(3)]
list_of_lists = [row for range in xrange(3)]
list_of_lists[1][1] = 'b'
for row in list_of_lists:
    print row

它会导致列表中的一整列项目被更改。为什么是这样?如何通过列表理解达到预期的效果?

4

3 回答 3

5

想想如果你这样做:

>>> row = ['a' for range in xrange(3)]
>>> row2 = row
>>> row2[0] = 'b'
>>> row
['b', 'a', 'a']

发生这种情况是因为rowand是同一个列表row2的两个不同名称(您有)-您的嵌套列表示例只会稍微掩盖这一点。row is row2

要使它们成为不同的列表,您可以使其每次重新运行列表创建代码,而不是进行变量赋值:

list_of_lists = [['a' for range in xrange(3)] for _ in xrange(3)]

或者,每次使用完整旧列表的一部分创建一个新列表:

list_of_lists = [row[:] for range in xrange(3)]

虽然这不能保证对所有序列都适用——只是列表切片会为切片创建一个新列表。这不会发生在例如 numpy 数组中——其中的切片是数组一部分的视图,而不是副本。如果您需要更一般地工作而不仅仅是列表,请使用该copy模块:

from copy import copy
list_of_lists = [copy(row) for range in xrange(3)]

另外,请注意,这range不是变量的最佳名称,因为它会隐藏内置函数 - 对于像这样的一次性使用,_是相当常见的。

于 2012-09-17T03:35:23.707 回答
2

发生这种情况是因为 python 中的大多数对象(字符串和数字除外)都通过引用(不完全是通过引用,但在这里你有更好的解释)所以当你尝试以“列表全面”的方式进行时,你会得到一个列表对同一列表的 3 个引用(您称为“行”的那个)。因此,当您更改一行的值时,您会看到所有行的值都发生了变化)

所以你要做的就是像这样改变你的“矩阵”创建:

list_of_lists = [list(row) for range in xrange(3)]

在这里,您对如何正确获取列表副本有一些想法。根据您要执行的操作,您可以使用一种或另一种...

希望能帮助到你!

于 2012-09-17T03:38:24.033 回答
0

复制列表而不仅仅是引用。

list_of_lists = [row[:] for range in xrange(3)]
于 2012-09-17T03:24:51.900 回答