Python iadd运算符(+;=)与简单加法有何不同?
我一直认为Python iadd运算符(+;=)与简单加法有何不同?,python,syntax,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] 它应该返回它得到的相同列表,
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可能不是“真实”的加法有关,但我仍然希望解释器将它们视为等价的
mylist += random.sample(range(100),2)
将列表mylist
就地修改(这就是为什么它被称为iadd
:就地添加)。这意味着它会更改调用方作用域中的原始列表
mylist = mylist[:-2]
创建一个新的本地对象mylist
,并将全局mylist[:-2]
的内容分配给它。这个新的本地对象从函数返回后立即被丢弃。行
mylist += random.sample(range(100),2)
将列表mylist
就地修改(这就是为什么它被称为iadd
:就地添加)。这意味着它会更改调用方作用域中的原始列表
mylist = mylist[:-2]
创建一个新的本地对象mylist
,并将全局mylist[:-2]
的内容分配给它。这个新的本地对象在从函数返回后立即被丢弃。第一个代码(mylist+=random.sample(范围(100),2)
)将修改列表,正如您所意识到的那样
这两项:
mylist = mylist + ...
mylist = mylist[:-2]
创建一个名为mylist
的新对象,然后为该对象指定与先前的mylist
相同的值(或从中派生的值)
由于这个原因,后一行不会恢复原始列表;它创建了一个新的副本,并保留了原始引用
通过更改适当的列表,您可以获得所需的行为:
mylist[:] = mylist[:-2]
第一个代码(mylist+=random.sample(范围(100),2)
)修改列表,正如您所意识到的那样
这两项:
mylist = mylist + ...
mylist = mylist[:-2]
创建一个名为mylist
的新对象,然后为该对象指定与先前的mylist
相同的值(或从中派生的值)
由于这个原因,后一行不会恢复原始列表;它创建了一个新的副本,并保留了原始引用
通过更改适当的列表,您可以获得所需的行为:
mylist[:] = mylist[:-2]
因为关于
global
的评论而试图否决投票。。。如果他添加了global mylist
,那么他的原始列表仍将被称为x
,因此代码肯定不会像预期的那样运行;使用globals来实现这一点肯定不是一个好办法。您可以在列表的开头复制列表,也可以在整个过程中对其进行修改,例如使用pop
两次,而不是在末尾进行切片。@l4mpi:您说得对,我应该删除此列表。谢谢。因为关于global
的评论,我很想投反对票。。。如果他添加了global mylist
,那么他的原始列表仍将被称为x
,因此代码肯定不会像预期的那样运行;使用globals来实现这一点肯定不是一个好办法。您可以在列表的开头复制列表,也可以在整个过程中对其进行修改,例如使用pop
两次,而不是在末尾进行切片。@l4mpi:您说得对,我应该删除此列表。谢谢,谢谢!现在,我知道为什么了。谢谢!现在,我知道为什么了。