在Python中为何选择就地进行列表增强赋值(+=)?

6 投票
7 回答
2580 浏览
提问于 2025-04-16 13:19
>>> list1 = []
>>> list2 = list1
>>> list2 += [1]
>>> print list1
[1]

把这个和

>>> list1 = []
>>> list2 = list1
>>> list2 = list2 + [1]
>>> print list1
[]

有没有什么原因导致'+='这个操作会修改原来的列表?

编辑:为了让我的问题更清楚一些

在我知道的大多数编程语言中,'+='这个操作符并不是这样工作的,我想知道为什么在Python中会设计成这样。

一些例子:

Ruby

irb(main):001:0> l = []
irb(main):002:0> a = l
irb(main):003:0> a += [2]
irb(main):004:0> l
=> []

Scala等等。

7 个回答

6

文档中查看关于模拟数字类型的内容,这里描述了实现这种行为的方法。这同样适用于列表:

这些方法是用来实现增强的算术赋值操作(比如+=, -=, *=, /=, //=, %=, **=, <<=, >>=, &=, ^=, |=)。这些方法应该尝试在原地进行操作(也就是直接修改self),并返回结果(这个结果可以是self,但不一定非得是)。如果某个特定的方法没有定义,那么增强赋值就会退回到普通的方法。例如,要执行语句x += y,假设x是一个有__iadd__()方法的类的实例,那么就会调用x.__iadd__(y)。如果x是一个没有定义__iadd__()方法的类的实例,那么就会考虑x.__add__(y)y.__radd__(x),这和计算x + y是一样的。

11

在Python中,列表是通过引用来存储的。

这意味着当你写 list2 = list1 的时候,你并不是在复制这个列表,而是在说 "list2 指向和 list1 一样的东西",也就是你最开始创建的那个列表,比如你写 list1 = [] 的时候。

Python中用 += 来表示“就地添加”这个意思,因为大多数时候你在列表上使用 +=,其实就是想要这样做——你通常不想每次添加一个元素时都创建一个新列表。

所以,当你往 list2 添加内容时,list2list1 指向的是同一个列表,这样你再去查看 list1 的时候,就能看到你刚添加的内容,因为它们指向的是同一个列表。

但是,使用 + 的时候,总是会创建一个新列表,因为这样做不涉及修改原来的任何一个列表(因为 a+b 并不意味着要修改 ab)。

因此,当你写 list2 = list2 + [1] 的时候,你实际上是创建了一个新列表,这个新列表包含了 list2 原来指向的所有内容,还有 1,然后你让 list2 现在指向这个新列表。因为现在 list2 指向的是一个和 list1 不同的列表,所以当你去查看 list1 的时候,依然能看到原来的列表,没有那个额外的 1

8

来自Python 2.6.4文档的第6.2.1节(增强赋值语句)

x += 1 这样的增强赋值表达式,可以写成 x = x + 1,虽然效果相似,但并不完全相同。在增强版本中,x 只会被计算一次。而且,当有可能的时候,实际的操作是在原地进行的,这意味着不是创建一个新对象然后把它赋值给目标,而是直接修改旧的对象。

[强调部分]

撰写回答