iadd运算符(+ =)与简单加法有何不同?

时间:2013-09-19 10:18:38

标签: python syntax

我一直以为x += 1只是句法简写(并且完全等同于)x = x + 1,直到我花了一段时间试图弄清楚为什么这段代码没有按照预期行事:

[ipython/euler 72 ]$ def func(mylist):
    mylist += random.sample(range(100),2)
    # do stuff with the random result, then restore original list
    mylist = mylist[:-2]

它应该返回它获得的相同列表,但它似乎没有那样工作:

[ipython/euler 81 ]$ x = [1,2,3]

[ipython/euler 82 ]$ func(x)
[1, 2, 3, 23, 7]

[ipython/euler 83 ]$ func(x)
[1, 2, 3, 23, 7, 42, 36]

[ipython/euler 84 ]$ func(x)
[1, 2, 3, 23, 7, 42, 36, 0, 5]

如果我将赋值语句更改为长格式mylist = mylist + ...,它将按预期工作并保持列表不变。

为什么会这样?我认为这与列表是可变的有关,并且当被称为列表的重载方法时可能不是“真正的”添加,但我仍然期望解释器将它们视为等效。

2 个答案:

答案 0 :(得分:3)

该行

mylist += random.sample(range(100),2)

就地改变列表mylist(这就是为什么它被称为iadd:就地添加)。这意味着它会更改调用者范围内的原始列表。

mylist = mylist[:-2]

创建一个新的本地对象mylist,并将全局mylist[:-2]的内容分配给它。然后在从函数返回时立即丢弃这个新的本地对象。

答案 1 :(得分:3)

第一个代码(mylist += random.sample(range(100),2))会修改列表到位,如您所知。

这两个:

mylist = mylist + ...
mylist = mylist[:-2]

创建一个名为mylist对象,然后将其赋予与之前mylist相同的值(或从中导出)。

由于这个原因,后一行不会恢复原始列表;它正在创建一个新副本,并保留原始参考。

您可以通过更改列表来获得所需的行为:

mylist[:] = mylist[:-2]