【问题标题】:What exactly does += do?+= 究竟是做什么的?
【发布时间】:2011-01-30 06:00:29
【问题描述】:

我需要知道+= 在 Python 中做了什么。就是这么简单。我也希望能提供指向 Python 中其他速记工具定义的链接。

【问题讨论】:

  • 它是python(以及许多其他语言)的基本运算符,如果您从未阅读过任何python参考资料,您应该从google开始。
  • @AndiDog 虽然这两个问题都是关于 (+=) 运算符的,但您链接的问题是关于复杂的用法和微妙的问题,这里的 OP 可能无法遵循那里的推理(还)。
  • @AndiDog 也许你当时是对的,但是看看这里(几乎)接受的解决方案,很明显这个问题是关于对运营商的基本了解:D
  • 大多数 sumbol 使用现在都在符号页面 docs.python.org/3/genindex-Symbols.html 中编入索引。

标签: python operators compound-assignment


【解决方案1】:

在 Python 中,+=__iadd__ 特殊方法的糖衣,如果__iadd__ 不存在,则__add____radd__。一个类的__iadd__ 方法可以做它想做的任何事情。列表对象实现了它并使用它来迭代一个可迭代对象,将每个元素附加到自身,就像列表的扩展方法一样。

这是一个实现__iadd__ 特殊方法的简单自定义类。您使用 int 初始化对象,然后可以使用 += 运算符添加一个数字。我在__iadd__ 中添加了一个打印语句,以表明它被调用了。另外,__iadd__ 应该返回一个对象,所以我返回了它自己加上另一个在这种情况下有意义的数字。

>>> class Adder(object):
        def __init__(self, num=0):
            self.num = num

        def __iadd__(self, other):
            print 'in __iadd__', other
            self.num = self.num + other
            return self.num
    
>>> a = Adder(2)
>>> a += 3
in __iadd__ 3
>>> a
5

希望这会有所帮助。

【讨论】:

  • 虽然这不是提问者想要的,但 +1 才是真正的答案。 =)
  • @Michael,这就是幽默增加事实的地方...... :-D
  • +1 用于回答问题,但 -1 用于返回不同类型的 __iadd__(它本身是可添加的)
  • 这个答案对于需要询问 += 含义的人(即初学者)来说太复杂了。您的答案不是初学者的答案,不仅因为初学者通常不会以面向对象的方式开始学习 Python,还因为有更简单的答案(如下面的@Imran)。只是我的两分钱,尽管我很欣赏这个答案。
  • 这不太正确,__iadd__ 只做了+= 的一半。文档:“计算和赋值是在两个单独的步骤中执行的。下面列出的就地函数只做第一步,调用就地方法。第二步,赋值,不处理。” docs.python.org/3/library/operator.html 部分:就地操作员。
【解决方案2】:

+= 将另一个值与变量的值相加,并将新值赋给变量。

>>> x = 3
>>> x += 2
>>> print x
5

-=*=/= 对减法、乘法和除法的作用类似。

【讨论】:

    【解决方案3】:

    x += 5 与 Python 中的 x = x + 5 并不完全相同。

    请注意:

    In [1]: x = [2, 3, 4]    
    
    In [2]: y = x    
    
    In [3]: x += 7, 8, 9    
    
    In [4]: x
    Out[4]: [2, 3, 4, 7, 8, 9]    
    
    In [5]: y
    Out[5]: [2, 3, 4, 7, 8, 9]    
    
    In [6]: x += [44, 55]    
    
    In [7]: x
    Out[7]: [2, 3, 4, 7, 8, 9, 44, 55]    
    
    In [8]: y
    Out[8]: [2, 3, 4, 7, 8, 9, 44, 55]    
    
    In [9]: x = x + [33, 22]    
    
    In [10]: x
    Out[10]: [2, 3, 4, 7, 8, 9, 44, 55, 33, 22]    
    
    In [11]: y
    Out[11]: [2, 3, 4, 7, 8, 9, 44, 55]
    

    参考:Why does += behave unexpectedly on lists?

    【讨论】:

    【解决方案4】:

    += 向变量添加一个数字,在过程中更改变量本身(而+ 不会)。与此类似,还有以下也修改了变量:

    • -=,从变量中减去一个值,将变量设置为结果
    • *=,将变量乘以一个值,使结果成为变量
    • /=,将变量除以值,使结果成为变量
    • %=,对变量进行取模,然后将变量设置为它的结果

    可能还有其他人。我不是 Python 程序员。

    【讨论】:

    • 对于数字,这个答案是正确的。 (有关特殊行为,请参阅 Bryan's answer。)还有其他几个 are indeed,包括位运算符(&=>>= 等)和其他数学运算符(**= 等)。
    【解决方案5】:

    它不仅仅是一种语法糖。试试这个:

    x = []                 # empty list
    x += "something"       # iterates over the string and appends to list
    print(x)               # ['s', 'o', 'm', 'e', 't', 'h', 'i', 'n', 'g']
    

    x = []                 # empty list
    x = x + "something"    # TypeError: can only concatenate list (not "str") to list
    

    += 运算符调用__iadd__() 列表方法,而+ 一个调用__add__() 一个。他们用列表做不同的事情。

    【讨论】:

    • 我对此感到非常困惑!感谢您的代码和解释。看起来 += 只对数字安全有效。我说的对吗?
    【解决方案6】:

    它将右边的操作数添加到左边。 x += 2 表示x = x + 2

    它还可以将元素添加到列表中——参见this SO thread

    【讨论】:

      【解决方案7】:

      名义上 a += b 将 b“添加”到 a 中,并将结果存储在 a 中。这种简单的描述可以描述多种语言中的 += 运算符。

      然而,简单的描述引发了几个问题。

      1. 我们所说的“添加”到底是什么意思?
      2. “将结果存储在 a”中究竟是什么意思? python 变量不直接存储值,它们存储对对象的引用。

      在 python 中,这两个问题的答案取决于 a 的数据类型。


      那么“加”到底是什么意思呢?

      • 对于数字,它意味着数字加法。
      • 对于列表、元组、字符串等,它意味着连接。

      请注意,对于列表 += 比 + 更灵活,列表上的 + 运算符需要另一个列表,但 += 运算符将接受任何可迭代的。


      那么“将值存储在 a”中是什么意思?

      如果对象是可变的,则鼓励(但不是必需)就地执行修改。所以 a 指向它之前所做的同一个对象,但该对象现在具有不同的内容。

      如果对象是不可变的,那么它显然不能就地执行修改。一些可变对象也可能没有就地“添加”操作的实现。在这种情况下,变量“a”将被更新为指向一个包含加法运算结果的新对象。

      从技术上讲,这是通过首先查找__IADD__ 来实现的,如果没有实现,则尝试__ADD__,最后尝试__RADD__


      在 python 中对我们不确定确切类型的变量使用 += 时需要小心,特别是在我们不确定类型是否可变的情况下。例如考虑下面的代码。

      def dostuff(a):
          b = a
          a += (3,4)
          print(repr(a)+' '+repr(b))
      
      dostuff((1,2))
      dostuff([1,2])
      

      当我们使用元组调用 dostuff 时,元组会作为 += 操作的一部分被复制,因此 b 不受影响。但是,当我们使用列表调用它时,列表会被原地修改,因此 a 和 b 都会受到影响。

      在 python 3 中,“bytes”和“bytearray”类型观察到类似的行为。


      最后请注意,即使对象没有被替换,也会发生重新分配。如果左侧只是一个变量,这并不重要,但是当您有一个引用可变集合的不可变集合时,它可能会导致混乱的行为,例如:

      a = ([1,2],[3,4])
      a[0] += [5]
      

      在这种情况下,[5] 将成功添加到由 a[0] 引用的列表中,但随后当代码尝试重新分配 a[0] 但失败时,将引发异常。

      【讨论】:

        【解决方案8】:

        注意x += yx = x + y 不同,在某些情况下,由于operator precedence 加上总是首先计算右侧的事实,例如

        >>> x = 2
        >>> x += 2 and 1
        >>> x
        3
        
        >>> x = 2
        >>> x = x + 2 and 1
        >>> x
        1
        

        注意第一种情况展开为:

        >>> x = 2
        >>> x = x + (2 and 1)
        >>> x
        3
        

        您更有可能在“现实世界”中与其他运营商一起遇到这种情况,例如

        x *= 2 + 1 == x = x * (2 + 1) != x = x * 2 + 1

        【讨论】:

          【解决方案9】:

          简短的回答是+= 可以翻译为“将 += 右侧的任何内容添加到 +=" 左侧的变量中。

          例如。如果您有a = 10,那么a += 5 将是:a = a + 5

          所以,“a”现在等于 15。

          【讨论】:

          • 这个答案有什么尚未讨论的贡献?这是一个重复的答案...
          • jdv,只是想帮忙。我是新的贡献者,如果您认为我的回答重复,请见谅。
          • 如果您查看大多数其他答案,很明显它是重复的。贡献是好的,但你应该努力贡献一些新的东西(例如,像 add vs iadd 答案)或者你想尝试一个更清晰的解决方案。但是,据我所知,投票最多的答案与基本答案一样清晰。
          【解决方案10】:

          +=只是写作的捷径

          number = 4
          number = number + 1
          

          所以你会写

          numbers = 4
          numbers += 1
          

          这两种方法都是正确的,但是示例二可以帮助您编写更少的代码

          【讨论】:

          • 数字上的行为是相同的,但总体上不一样。
          【解决方案11】:

          根据documentation

          x += y 等价于x = operator.iadd(x, y)。另一种方法 也就是说z = operator.iadd(x, y)相当于 复合语句z = x; z += y.

          所以x += 3x = x + 3 相同。

          x = 2
          
          x += 3
          
          print(x)
          

          将输出 5。

          注意还有

          【讨论】:

            【解决方案12】:

            让我们看看 CPython 为x += yx = x = y 生成的字节码。 (是的,这是依赖于实现的,但它让您了解正在实现的语言定义的语义。)

            >>> import dis
            >>> dis.dis("x += y")
              1           0 LOAD_NAME                0 (x)
                          2 LOAD_NAME                1 (y)
                          4 INPLACE_ADD
                          6 STORE_NAME               0 (x)
                          8 LOAD_CONST               0 (None)
                         10 RETURN_VALUE
            >>> dis.dis("x = x + y")
              1           0 LOAD_NAME                0 (x)
                          2 LOAD_NAME                1 (y)
                          4 BINARY_ADD
                          6 STORE_NAME               0 (x)
                          8 LOAD_CONST               0 (None)
                         10 RETURN_VALUE
            

            两者之间的唯一区别在于用于运算符的字节码:INPLACE_ADD 用于+=BINARY_ADD 用于+

            BINARY_ADD 使用x.__add__(或y.__radd__,如果需要)实现,所以x = x + yx = x.__add__(y) 大致相同。 __add____radd__ 通常都返回新实例,而不修改任何一个参数。

            INPLACE_ADD 使用x.__iadd__ 实现。如果不存在,则使用x.__add__ 代替它。 x.__iadd__ 通常返回 x,因此生成的 STORE_NAME 不会更改 x 的所指对象,尽管该对象可能已发生变异。 (事实上​​,INPLACE_ADD 的目的是提供一种改变对象的方法,而不是总是创建一个新对象。)

            例如,int.__iadd__ 未定义,因此当xint 时,x += 7x = x.__add__(y) 相同,将x 设置为int 的新实例。

            另一方面,list.__iadd__ 已定义,因此当xlist 时,x += [7]x = x.__iadd__([9]) 相同。 list.__iadd__ 有效地调用extend 将其参数的元素添加到x 的末尾。在增强赋值前后查看 x 的值实际上无法判断 x 被重新赋值,因为 same 对象已赋值给该名称。

            【讨论】:

              【解决方案13】:

              正如其他人所说,+= 运算符是一种快捷方式。 一个例子:

              var = 1;
              var = var + 1;
              #var = 2
              

              也可以这样写:

              var = 1;
              var += 1;
              #var = 2
              

              因此,您可以编写第二个示例,而不是编写第一个示例,这样就可以了。

              【讨论】:

                【解决方案14】:

                请记住,当您过去在旧计算器中求和(例如 2 和 3)时,每次点击 = 时,您都会看到总数增加了 3,+= 执行类似的工作。示例:

                >>> orange = 2
                >>> orange += 3
                >>> print(orange)
                5
                >>> orange +=3
                >>> print(orange)
                8
                

                【讨论】:

                  【解决方案15】:

                  我看到很多没有使用 += 和多个整数的答案。

                  一个例子:

                  x -= 1 + 3
                  

                  这类似于:

                  x = x - (1 + 3)
                  

                  而不是:

                  x = (x - 1) + 3
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2013-02-20
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2020-05-13
                    • 2016-12-07
                    相关资源
                    最近更新 更多