x = x + 1和x + = 1之间的Python区别[重复]
Posted
技术标签:
【中文标题】x = x + 1和x + = 1之间的Python区别[重复]【英文标题】:Python Difference between x = x+1 and x += 1 [duplicate] 【发布时间】:2012-10-06 00:00:32 【问题描述】:在Python中,写x = x+1
和x += 1
之间有什么区别(语义、效率等)?
【问题讨论】:
【参考方案1】:是的。根据 x
类的编码方式,短格式可以选择就地修改 x,而不是创建一个表示总和的新对象并将其重新绑定回相同的名称。如果您有多个变量都引用同一个对象 - 例如,列表:
>>> a = b = []
>>> a += [5]
>>> a
[5]
>>> b
[5]
>>> a = a + [5]
>>> a
[5, 5]
>>> b
[5]
发生这种情况是因为在幕后,操作员调用了不同的魔法方法:+
调用 __add__
或 __radd__
(预计不会修改它们的任何一个参数)和 +=
尝试 __iadd__
(这如果__iadd__
不存在,则允许在退回到+
逻辑之前修改self
。
【讨论】:
【参考方案2】:它们对于整数和浮点数几乎相同,但对于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
【讨论】:
【参考方案3】:它们是不同的,因为+
和+=
有不同的运算符。使用x = x + 1
,解释器会将其视为x = x.__add__(1)
,而x += 1
将是x = x.__iadd(1)
,这样效率更高,因为它不一定需要复制x
。
【讨论】:
x += 1
实际上变成了x = x.__iadd__(1)
,而不仅仅是x.__iadd__(1)
- 即使是self
,i*
魔术方法仍有望返回它们的结果(重要的是,根据您链接的文档,它不必是 self)。另请参阅 Lattyware 的答案中它们的反汇编 - 两个版本都有 STORE_FAST
。
@lvc 谢谢,我更新了我的答案。【参考方案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
s 是不可变的。从理论上讲,它们可以以不同的方式实现(取决于解释器),但这不会改变它对值的操作方式。
一般来说,它们可以被实现来做完全不同的事情(+
被魔术方法__add__()
和+=
和__iadd()__
实现) - 例如,在大多数可变容器中,它会产生巨大的区别,如果你有不同的名字引用同一个对象:
>>> x = []
>>> y = x
>>> x += [1]
>>> y
[1]
>>> x = x + [1]
>>> y
[1]
>>> x
[1, 1]
您可以看到,当我们将x
分配给y
时,它们都指向同一个列表。当我们使用+=
时,我们扩展了列表并且两者都发生了变化。当我们为x
分配新值时,y
仍然指向原始值并保持不变。
【讨论】:
以上是关于x = x + 1和x + = 1之间的Python区别[重复]的主要内容,如果未能解决你的问题,请参考以下文章
x = x + 1和x + = 1之间的Python区别[重复]
CodeIgniter 错误报告 1.7.x 和 2.x 之间的区别