为什么foo.append(bar)会影响列表列表中的所有元素?

时间:2011-06-15 15:31:25

标签: python list append

我创建了一个列表列表,并希望将项目附加到各个列表,但是当我尝试附加到其中一个列表(a[0].append(2))时,该项目将添加到所有列表中。

a = []
b = [1]

a.append(b)
a.append(b)

a[0].append(2)
a[1].append(3)
print(a)

给予:[[1, 2, 3], [1, 2, 3]]

我希望:[[1, 2], [1, 3]]

更改构建初始列表列表的方式,使b成为浮点而不是列表并将括号放在.append()中,为我提供了所需的输出:

a = []
b = 1

a.append([b])
a.append([b])

a[0].append(2)
a[1].append(3)
print(a)

给予:[[1, 2], [1, 3]]

但为什么呢?结果应该不同是不直观的。我知道这与multiple references to the same list有关,但我不知道发生了什么。

3 个答案:

答案 0 :(得分:23)

这是因为列表包含对象的引用。您的列表不包含[[1 2 3] [1 2 3]],它是[<reference to b> <reference to b>]

当您更改对象时(通过向b添加内容),您将更改对象本身,而不是包含该对象的列表。

要获得所需效果,您的列表a必须包含b的副本,而不是b的引用。要复制列表,您可以使用范围[:]。例如,:

>>> a=[]
>>> b=[1]
>>> a.append(b[:])
>>> a.append(b[:])
>>> a[0].append(2)
>>> a[1].append(3)
>>> print a
[[1, 2], [1, 3]]

答案 1 :(得分:2)

关键是这一部分:

a.append(b)
a.append(b)

您要将相同的列表追加两次,因此a[0]a[1]都是对同一列表的引用。

在第二个示例中,每次调用像a.append([b])这样的追加时,都会创建新列表,因此它们是使用相同浮点值初始化的单独对象。

答案 2 :(得分:1)

为了制作列表的浅表副本,这个成语是

a.append(b[:])

当加倍时会导致a有两个新的列表b的副本,这些副本不会给你报告的别名错误。