在python中进行列表扩充赋值(+ =)的动机是什么?

mko*_*ela 5 python

>>> list1 = []
>>> list2 = list1
>>> list2 += [1]
>>> print list1
[1]
Run Code Online (Sandbox Code Playgroud)

比较这个

>>> list1 = []
>>> list2 = list1
>>> list2 = list2 + [1]
>>> print list1
[]
Run Code Online (Sandbox Code Playgroud)

有没有理由为什么'+ =' - 操作会修改原始列表?

编辑:只是为了让我的问题更清楚一点

在我所知道的大多数语言中,'+ =' - 运算符不能以这种方式工作,我想知道它为什么在python中以这种方式设计.

一些例子:

红宝石

irb(main):001:0> l = []
irb(main):002:0> a = l
irb(main):003:0> a += [2]
irb(main):004:0> l
=> []
Run Code Online (Sandbox Code Playgroud)

斯卡拉等..

Amb*_*ber 10

通过引用存储的Python列表.

这意味着,当你这样做时list2 = list1,你不会复制列表 - 你只是说" list2指的是同一个东西list1",即你最初创建的列表list1 = [].

Python指定+=为列表"附加到位",因为大多数情况下,当您+=在列表上使用时,这就是您想要做的事情 - 您通常不希望每次添加元素时都创建新列表.

因此,当您追加到list2"引用同一个对象list1时",然后从中读取时list1,您会看到附加项,因为它们都指向同一个列表.

有了+,但是,总是会创建一个新的列表,因为它没有任何意义修改两个操作数到位(因为a+b并不意味着修改ab).

因此,当你做list2 = list2 + [1],你创建了所有的原始对象的内容指向一个新的列表list2,并1,然后说,list2现在引用新的列表.由于它现在引用了一个不同的列表list1,当你去阅读时list1仍然可以看到没有额外的原始列表1.


Odd*_*ing 7

从Python 2.6.4文档,第6.2.1节.(增强的赋值语句)

增强的赋值表达式x += 1可以被重写为x = x + 1实现类似但不完全相同的效果.在增强版本中,x仅评估一次.此外,在可能的情况下,实际操作是就地执行的,这意味着不是创建新对象并将其分配给目标,而是修改旧对象.

[强调补充]

  • 关于背景中发生的事情的一点额外解释:实际上,这两个赋值不使用相同对象的方法,这就是行为不同的原因.`x = x + 1`使用`__add __()`方法,它返回一个新对象,而`x + = 1`使用`__iadd __()`方法,该方法就地修改对象. (2认同)

Fel*_*ing 5

请参阅有关模拟数字类型文档,该文档描述了实现此行为的方法.这也适用于列表:

调用这些方法来实现增强算术赋值(+=, -=, *=, /=, //=, %=, **=, <<=, >>=, &=, ^=, |=).这些方法应该尝试就地进行操作(修改self)并返回结果(可能是,但不一定是这样self).如果未定义特定方法,则扩充分配将回退到常规方法.例如,要执行语句x += y,调用x具有__iadd__()方法的类的实例x.__iadd__(y).If x是一个没有定义__iadd__()方法的类的实例,x.__add__(y)并且y.__radd__(x)被考虑,就像评估一样x + y.