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

Posted

技术标签:

【中文标题】iadd 运算符 ( += ) 与简单加法有何不同? [复制]【英文标题】:How is the iadd operator ( += ) different than simple addition? [duplicate] 【发布时间】:2013-09-24 09:10:12 【问题描述】:

我一直认为 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 + ...,它会按预期工作并且保持列表不变。

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

【问题讨论】:

【参考方案1】:

线

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

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

mylist = mylist[:-2]

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

【讨论】:

因为global 的评论而想投反对票... ;并且为此使用全局变量肯定不是要走的路。您要么想在开头复制列表,要么一直在原地修改它,例如使用pop 两次而不是在末尾切片。 @l4mpi:你说得对,我应该删除它。谢谢。【参考方案2】:

如您所知,第一个代码 (mylist += random.sample(range(100),2)) 就地修改了列表

这两个:

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

创建一个名为mylist 对象,然后为其赋予与前一个mylist 相同的值(或派生自)。

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

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

mylist[:] = mylist[:-2]

【讨论】:

谢谢!现在,我知道为什么了。

以上是关于iadd 运算符 ( += ) 与简单加法有何不同? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

"||=" 运算符与 CoffeeScript 中的 "?=" 有何不同?

运算或算术指令

智能转换与 KOTLIN 中的显式转换有何不同

`var[:] = []` 与 `var = []` 有何不同? [复制]

图像上对的算术运算

什么是数组“属性列表”,它们与简单对象有何不同?