【问题标题】:Python Difference between x = x+1 and x += 1 [duplicate]x = x + 1和x + = 1之间的Python区别[重复]
【发布时间】:2012-10-06 00:00:32
【问题描述】:

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

【问题讨论】:

    标签: python


    【解决方案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) - 即使是selfi* 魔术方法仍有望返回它们的结果(重要的是,根据您链接的文档,它不必是 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         
        

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

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-06-14
          • 2014-04-16
          • 1970-01-01
          • 2021-01-24
          • 2017-03-02
          • 2018-06-18
          相关资源
          最近更新 更多