在Python中,写x = x+1
和x += 1
之间是否存在差异(语义,效率等)?
答案 0 :(得分:14)
是。根据{{1}}类的编码方式,短格式可以选择就地修改x,而不是创建表示总和的新对象并将其重新绑定到相同的名称。如果你有多个变量引用同一个对象,这就有了意义 - 例如,使用list:
x
这是因为在幕后操作员调用了不同的魔术方法:>>> a = b = []
>>> a += [5]
>>> a
[5]
>>> b
[5]
>>> a = a + [5]
>>> a
[5, 5]
>>> b
[5]
调用+
或__add__
(预期不会修改他们的任何一个参数)和{{1尝试__radd__
(如果感觉像是+=
则允许修改__iadd__
,如果self
不存在,则回退到+
逻辑。
答案 1 :(得分:5)
对于整数和浮点数,它们几乎相同,但lists
:
lis = lis+['foo']
通过连接lis
和['foo']
创建新列表,然后将结果分配给lis
和:
lis += [foo]
相当于lis.extend([foo])
>>> lis = [1,2,3]
>>> id(lis)
3078880140L
>>> lis += ['foo'] #or lis.extend(['foo'])
>>> id(lis) #same object
3078880140L
>>> lis = [1,2,3]
>>> id(lis)
3078880076L
>>> lis = lis+['foo']
>>> id(lis) #new object
3078880012L
答案 2 :(得分:4)
是的,它们是编译为不同字节码的不同运算符:
>>> import dis
>>> def test1(x):
... x = x + 1
...
>>> def test2(x):
... x += 1
...
>>> dis.dis(test1)
2 0 LOAD_FAST 0 (x)
3 LOAD_CONST 1 (1)
6 BINARY_ADD
7 STORE_FAST 0 (x)
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
>>> dis.dis(test2)
2 0 LOAD_FAST 0 (x)
3 LOAD_CONST 1 (1)
6 INPLACE_ADD
7 STORE_FAST 0 (x)
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
在这种情况下,它不会产生巨大的差异,因为int
是不可变的。从理论上讲,它们可以以不同的方式实现(取决于解释器),但这不会改变它对值的操作方式。
一般情况下,它们可以实现完全不同的东西(+
由魔术方法__add__()
和+=
与__iadd()__
实现) - 在大多数可变容器中例如,如果你有不同的名称引用同一个对象,它会产生很大的不同:
>>> x = []
>>> y = x
>>> x += [1]
>>> y
[1]
>>> x = x + [1]
>>> y
[1]
>>> x
[1, 1]
您可以看到,当我们将x
分配给y
时,它们都指向同一个列表。当我们使用+=
时,我们会扩展列表并进行更改。当我们为x
分配新值时,y
仍然指向原始值并保持不变。
答案 3 :(得分:2)
它们不同,因为+
和+=
有单独的运算符。对于x = x + 1
,解释器会将其视为x = x.__add__(1)
,而x += 1
将为x = x.__iadd(1)
,这可能会更有效率,因为它不一定需要制作x
。