+ = 到底是做什么的?

我需要知道 +=在 Python 中是做什么的。就这么简单。我还希望获得到 Python 中其他速记工具定义的链接。

798280 次浏览

+=使用变量的值添加另一个值,并将新值赋给变量。

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

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

它将右操作数添加到左操作数

它还可以向列表中添加元素——请参见 这个线索

+=向变量添加一个数字,在过程中改变变量本身(而 +不会)。与此类似,下面的代码也可以修改变量:

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

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

在 Python 中,+=是用于 __iadd__特殊方法的糖衣,如果 __iadd__不存在 __add____radd__。类的 __iadd__方法可以做任何它想做的事情。列表对象实现它,并使用它来迭代一个可迭代的对象,该对象将每个元素附加到自己,方式与列表的扩展方法相同。

下面是一个实现 __iadd__特殊方法的简单自定义类。使用 int 初始化对象,然后可以使用 +=运算符添加数字。我在 __iadd__中添加了一个 print 语句来显示它被调用。而且,__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

希望这个能帮上忙。

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

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

也可以这样写:

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

所以不用写第一个例子,你可以写第二个例子,这样就行了。

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

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

VS

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

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

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]

参见: 为什么 + = 在列表中表现得出乎意料?

记住,当你用你的旧计算器,例如2和3的总和,每次你击中的 =你看到3添加到总数,+=做类似的工作。例如:

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

+=只是写作的捷径

number = 4
number = number + 1

所以相反,你会写

numbers = 4
numbers += 1

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

概念上,a + = b 将 b“添加”到将结果存储在。这种过于简单的描述将在许多语言中描述 + = 运算符。

然而,过于简单的描述引发了一些问题。

  1. 我们说的“加法”到底是什么意思?
  2. 我们说的“将结果存储在”到底是什么意思?Python 变量不直接存储值,而是存储对对象的引用。

在 python 中,这两个问题的答案都取决于。


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

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

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


那么“在 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 都会受到影响。

在 python3中,可以观察到类似的“ byte”和“ bytearray”类型。


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

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

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

简短的答案是 +=可以翻译为“把 + = 右边的任何东西加到 + = 左边的变量”。

如果你有 a = 10,那么 a += 5就是: a = a + 5

所以“ a”现在等于15。

注意,在某些情况下,x += yx = x + y是不一样的,因为 运算符优先级与右边总是先求值的事实相结合,所以包含了一个额外的操作符,例如。

>>> 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 = x * (2 + 1)! = x = x * 2 + 1

我看到很多答案都没有使用 + = 来处理多个整数。

举个例子:

x -= 1 + 3

这将类似于:

x = x - (1 + 3)

而不是:

x = (x - 1) + 3

根据 文件

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。

注意,还有

让我们看看 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是否被重新赋值是不可能的,因为 x += [7]0对象被赋值给名称。

+=减少了添加两个具有给定变量的对象时的冗余:

长版本:

a = 10
a = a + 7
print(a)  # result is 17

简短版本:

a = 10
a += 7
print(a)  # result is 17

它基本上是说(变量) = (变量) + x 的简化 例如:

num = num + 2

与:

num += 2