当我定义一个列表并尝试像这样更改单个项目时:
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
它会导致列表中的整列项目被更改。为什么是这样?如何通过列表推导达到预期的效果?
请您参考如下方法:
想想如果你这样做:
>>> row = ['a' for range in xrange(3)]
>>> row2 = row
>>> row2[0] = 'b'
>>> row
['b', 'a', 'a']
发生这种情况是因为row 和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 数组中——其中的一个切片是数组的一部分的 View 而不是副本。如果您需要处理的不仅仅是列表,请使用 copy 模块:
from copy import copy
list_of_lists = [copy(row) for range in xrange(3)]
另外,请注意 range 不是变量的最佳名称,因为它隐藏了内置函数 - 对于像这样的一次性变量,_ 是相当常见的。
