添加到列表与增量

6 投票
3 回答
1227 浏览
提问于 2025-04-17 07:37

在Python中:

element = element + [0]

应该等于:

element += [0]

为什么一个会改变列表,而另一个不会呢?这里有个例子:

>>> a = [[0, 0], [0,0]]
>>> for element in a:
...     element = element + [0]
... 
>>> a
[[0, 0], [0, 0]]

a没有被改变。但是如果我增加:

>>> a = [[0, 0], [0,0]]
>>> for element in a:
...     element += [0]
...
>>> a
[[0, 0, 0], [0, 0, 0]]

a就被改变了。

谢谢,

Frank

3 个回答

2

补充一下其他人说的内容,这些语句的作用是有区别的:

element = element + [0]

做了什么

element = element.__add__([0])

element += [0]

做了什么

element = element.__iadd__([0])

__iadd__()这个方法可以决定返回什么:是修改过的原对象,还是一个新对象。

对于不可变对象,它必须返回一个不同的对象(例如,a = b = 8; a += 9 结果是 a 和 b 不相同)。

但对于可变对象,比如列表,它通常会修改原来的对象:

a = b = []
a += [8]

结果是 a 和 b 是相同的

这种不同的行为在你的循环中也会体现出来:

for element in a:
   element = element + [0]

这意味着 name 这个 element 被重新绑定到了一个不同的对象;原来的对象没有被改变。

for element in a:
   element += [0]

原来的对象,仍然在外部列表 a 中,也会被修改。element 被重新赋值这件事并不重要;它并没有被使用。

3

在第一个例子中,element = element + [0],你实际上是在创建一个新的列表。

而在第二个例子中,element += [0],你是在修改一个已经存在的列表。

因为列表 a 中的每个列表都是指向元素的指针,所以只有修改这些元素才会真正改变内容。(也就是说,创建一个新列表并不会改变 a 中的指针。)

如果我们用一个简单的例子来展示列表是如何工作的,这一点会更清楚:

>>> a = [1, 2, 3]
>>> b = a
>>> a = [4, 5, 6]
>>> a
[4, 5, 6]
>>> b
[1, 2, 3]
>>> a = [1, 2, 3]
>>> b = a
>>> a += [4, 5, 6]
>>> b
[1, 2, 3, 4, 5, 6]
>>> a
[1, 2, 3, 4, 5, 6]

把一个变量指向一个列表,其实就是在指向这个列表的地址。

7

这是一个有趣的现象,跟 += 这个操作符有关,它会调用 __iadd__ 方法,而不是 __add__ 方法。

比如说,语句 x = x + y 实际上等同于 x = x.__add__(y),而 x += y 则等同于 x = x.__iadd__(y)

这样一来,list 类就可以通过扩展现有的列表来优化 += 的操作(也就是说,x += y 大致上等同于 x.extend(y)),而不是创建一个全新的列表(这正是 + 操作需要做的事情)。

举个例子:

>>> a = [1, 2, 3]
>>> original_a = a
>>> b = [1, 2, 3]
>>> original_b = b
>>> a += [4]
>>> b = b + [4]
>>> a is original_a
True
>>> b is original_b
False

你可以看到,使用 += 时,左边的对象保持不变(也就是说,没有 创建一个新的列表),而使用 + 时则会创建一个新的列表(也就是说, 创建了一个新的列表)。

想了解更多,可以查看:http://docs.python.org/library/operator.html#operator.iadd,以及文档中 operator.iadd 相关段落的内容。

撰写回答