16

x = x+1在 Python 中,写和写之间有什么区别(语义、效率等)x += 1吗?

4

4 回答 4

17

是的。根据类的x编码方式,短格式可以选择就地修改 x,而不是创建一个表示总和的新对象并将其重新绑定回相同的名称。如果您有多个变量都引用同一个对象,则这意味着 - 例如,使用列表:

>>> a = b = []
>>> a += [5]
>>> a
[5]
>>> b
[5]
>>> a = a + [5]
>>> a
[5, 5]
>>> b
[5]

发生这种情况是因为在幕后,操作员调用了不同的魔法方法:+调用__add____radd__(预计不会修改它们的任何一个参数)和+=尝试(如果感觉__iadd__可以修改),然后返回到逻辑 if is不在那里。self+__iadd__

于 2012-10-15T23:21:53.123 回答
6

它们对于整数和浮点数几乎相同,但对于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
于 2012-10-15T23:22:00.823 回答
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         

在这种情况下,它不会有太大的不同,因为ints 是不可变的。从理论上讲,它们可以以不同的方式实现(取决于解释器),但这不会改变它对值的操作方式。

一般来说,它们可以被实现来做完全不同的事情(+通过魔法方法__add__()+=with实现__iadd()__)——例如,在大多数可变容器中,如果你有不同的名称引用同一个对象,它就会产生巨大的差异:

>>> x = []
>>> y = x
>>> x += [1]
>>> y
[1]
>>> x = x + [1]
>>> y
[1]
>>> x
[1, 1]

您可以看到,当我们分配x给 时y,它们都指向同一个列表。当我们使用 时+=,我们扩展了列表并且两者都改变​​了。当我们为 分配新值时xy仍然指向原始值并保持不变。

于 2012-10-15T23:20:23.107 回答
2

+它们是不同的,因为和有单独的运算符+=。有了x = x + 1,解释器会像对待它一样对待它x = x.__add__(1),而x += 1将会是x = x.__iadd(1),这会更有效率,因为它不一定需要复制x.

于 2012-10-15T23:24:25.580 回答