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

22 投票
4 回答
8864 浏览
提问于 2025-04-16 19:37

我创建了一个列表的列表,想要往每个小列表里添加东西。但是当我尝试往其中一个小列表里添加元素(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]]

但是为什么会这样呢?这个结果看起来并不直观。我知道这和有多个引用指向同一个列表有关,但我不明白具体是哪里出了问题。

4 个回答

1

为了制作一个列表的浅拷贝,通常的做法是

a.append(b[:])

这样做后,变量会有两个新的列表副本b,这样就不会出现你提到的别名问题了。

2

关键在于这一部分:

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

你在添加同一个列表两次,所以 a[0]a[1] 都指向同一个列表。

在你的第二个例子中,每次你调用 a.append([b]) 时,都是在创建新的列表,所以它们是独立的对象,虽然它们的初始值都是相同的浮点数。

39

这是因为列表里存的是对象的引用。你的列表里并不是直接包含 [[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]]

撰写回答