我需要知道python中的+ =做了什么。就这么简单。我也很欣赏python中其他简写工具定义的链接。
答案 0 :(得分:112)
在Python中,+ =是__iadd__
特殊方法的糖涂层,如果__add__
不存在,则为__radd__
或__iadd__
。类的__iadd__
方法可以做任何想做的事情。 list对象实现它并使用它迭代一个可迭代对象,将每个元素附加到自身,方法与list的extend方法相同。
这是一个实现__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
希望这有帮助。
答案 1 :(得分:94)
+=
使用变量的值添加另一个值,并将新值赋给变量。
>>> x = 3
>>> x += 2
>>> print x
5
-=
,*=
,/=
对减法,乘法和除法的作用相似。
答案 2 :(得分:26)
+=
向变量添加一个数字,在过程中更改变量本身(而+
则不会)。与此类似,还有以下内容也修改了变量:
-=
,从变量中减去一个值,将变量设置为结果*=
,将变量和值相乘,使结果成为变量/=
,将变量除以值,使结果成为变量%=
,对变量执行模数,然后将变量设置为其结果可能还有其他人。我不是Python程序员。
答案 3 :(得分:24)
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]
答案 4 :(得分:16)
它在左边添加了右操作数。 x += 2
表示x = x + 2
它还可以向列表中添加元素 - 请参阅this SO thread。
答案 5 :(得分:14)
这不仅仅是一种语法快捷方式。试试这个:
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 列表方法,但+调用添加,这会对列表执行不同的操作。
答案 6 :(得分:7)
从概念上讲,+ = b"添加" b将结果存储在a中。这种简单的描述将描述许多语言中的+ =运算符。
然而,简单的描述提出了几个问题。
在python中,这两个问题的答案都取决于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中,使用"字节"观察到类似的行为。和" bytearray"类型。
最后请注意,即使没有替换对象,也会发生重新分配。如果左侧只是一个变量,这并不重要,但如果您有一个引用可变集合的不可变集合,它可能会导致令人困惑的行为,例如:
a = ([1,2],[3,4])
a[0] += [5]
在这种情况下,[5]将成功添加到[0]引用的列表中,但之后在代码尝试时将引发异常,并且无法重新分配[0]。
答案 7 :(得分:3)
+=
只是写作的捷径
numbers = 1
numbers = numbers + 1
print (numbers) ## 2
所以你会写
numbers = 1
numbers += 1
print (numbers) ## 2
两种方式都是正确的,但是示例二可以帮助您编写更少的代码
答案 8 :(得分:1)
简短的回答是+=
可以翻译为“将+ =右边的任何内容添加到+ =“左边的变量。
例如如果您有a = 10
,则a += 5
为:a = a + 5
因此,“ a”现在等于15。
答案 9 :(得分:1)
请注意,x += y
与x = 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
答案 10 :(得分:0)
正如其他人所说,+ =运算符是一种捷径。 一个例子:
var = 1;
var = var + 1;
#var = 2
也可以这样写:
var = 1;
var += 1;
#var = 2
所以不要写第一个例子,你可以写第二个例子,这样就可以了。
答案 11 :(得分:0)
请记住以前用过的时间,例如2& 3,在您的旧计算器中,每当您点击=
时,您看到3添加到总计算中,+=
执行类似的工作。例如:
>>> orange = 2
>>> orange += 3
>>> print(orange)
5
>>> orange +=3
>>> print(orange)
8
答案 12 :(得分:0)
我看到很多使用+ =并带有多个整数的答案。
一个例子:
x -= 1 + 3
这类似于:
x = x - (1 + 3)
而不是:
x = (x - 1) + 3
答案 13 :(得分:0)
x += y
等效于x = operator.iadd(x, y)
。另一种方式 可以说z = operator.iadd(x, y)
等于 复合语句z = x; z += y
。
所以x += 3
与x = x + 3
相同。
x = 2
x += 3
print(x)
将输出5。
请注意,还有
答案 14 :(得分:0)
让我们看看 CPython 为 x += y
和 x = 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
用于 +
。< /p>
BINARY_ADD
是使用 x.__add__
(或 y.__radd__
如有必要)实现的,因此 x = x + y
与 x = x.__add__(y)
大致相同。 __add__
和 __radd__
通常都返回新实例,而不修改任何一个参数。
INPLACE_ADD
是使用 x.__iadd__
实现的。如果不存在,则使用 x.__add__
代替。 x.__iadd__
通常返回 x
,因此结果 STORE_NAME
不会更改 x
的所指对象,尽管该对象可能已发生变异。 (实际上,INPLACE_ADD
的目的是提供一种改变对象的方法,而不是总是创建一个新对象。)
例如,int.__iadd__
未定义,因此 x += 7
当 x
是 int
时与 x = x.__add__(y)
相同,设置 x
到 int
的新实例。
另一方面,定义了list.__iadd__
,所以当x += [7]
是x
时,list
与x = x.__iadd__([9])
相同。 list.__iadd__
有效地调用 extend
将其参数的元素添加到 x
的末尾。通过查看增强赋值前后 x
的值实际上无法判断 x
被重新赋值,因为 same 对象被分配给名称。< /p>