为啥 foo.append(bar) 会影响列表列表中的所有元素?
Posted
技术标签:
【中文标题】为啥 foo.append(bar) 会影响列表列表中的所有元素?【英文标题】:Why does foo.append(bar) affect all elements in a list of lists?为什么 foo.append(bar) 会影响列表列表中的所有元素? 【发布时间】:2011-09-15 15:51:06 【问题描述】:我创建了一个列表列表并希望将项目附加到各个列表中,但是当我尝试附加到其中一个列表 (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 的存在有关,但我不知道发生在哪里。
【问题讨论】:
【参考方案1】:这是因为列表包含对对象的引用。您的列表不包含[[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]]
【讨论】:
谢谢,现在很有意义。【参考方案2】:关键是这部分:
a.append(b)
a.append(b)
您将同一个列表追加两次,因此a[0]
和a[1]
都是对同一个列表的引用。
在第二个示例中,每次调用 append 时都会创建新列表,例如 a.append([b])
,因此它们是使用相同浮点值初始化的单独对象。
【讨论】:
谢谢,这个回答也增加了我的理解。【参考方案3】:为了做一个列表的浅拷贝,成语是
a.append(b[:])
当它加倍时,会导致 a 有两个新的列表 b
副本,这不会给您报告的别名错误。
【讨论】:
以上是关于为啥 foo.append(bar) 会影响列表列表中的所有元素?的主要内容,如果未能解决你的问题,请参考以下文章