为什么+ =在列表上表现异常? [英] Why does += behave unexpectedly on lists?
问题描述
python中的+=
运算符似乎在列表上意外运行.谁能告诉我这是怎么回事?
The +=
operator in python seems to be operating unexpectedly on lists. Can anyone tell me what is going on here?
class foo:
bar = []
def __init__(self,x):
self.bar += [x]
class foo2:
bar = []
def __init__(self,x):
self.bar = self.bar + [x]
f = foo(1)
g = foo(2)
print f.bar
print g.bar
f.bar += [3]
print f.bar
print g.bar
f.bar = f.bar + [4]
print f.bar
print g.bar
f = foo2(1)
g = foo2(2)
print f.bar
print g.bar
输出
[1, 2]
[1, 2]
[1, 2, 3]
[1, 2, 3]
[1, 2, 3, 4]
[1, 2, 3]
[1]
[2]
foo += bar
似乎影响该类的每个实例,而foo = foo + bar
似乎以我希望事情表现的方式表现.
foo += bar
seems to affect every instance of the class, whereas foo = foo + bar
seems to behave in the way I would expect things to behave.
+=
运算符称为化合物赋值运算符".
The +=
operator is called a "compound assignment operator".
推荐答案
通常的答案是+=
尝试调用__iadd__
特殊方法,如果该方法不可用,它将尝试使用__add__
.因此,问题在于这些特殊方法之间的差异.
The general answer is that +=
tries to call the __iadd__
special method, and if that isn't available it tries to use __add__
instead. So the issue is with the difference between these special methods.
__iadd__
特殊方法用于就地加法,即,它会改变作用于其上的对象. __add__
特殊方法返回一个新对象,也用于标准+
运算符.
The __iadd__
special method is for an in-place addition, that is it mutates the object that it acts on. The __add__
special method returns a new object and is also used for the standard +
operator.
因此,当在定义了__iadd__
的对象上使用+=
运算符时,该对象将被修改.否则,它将尝试使用普通的__add__
并返回一个新对象.
So when the +=
operator is used on an object which has an __iadd__
defined the object is modified in place. Otherwise it will instead try to use the plain __add__
and return a new object.
这就是为什么对于诸如列表+=
之类的可变类型会更改对象的值,而对于诸如元组,字符串和整数之类的不可变类型则会返回一个新对象的原因(a += b
等同于a = a + b
).
That is why for mutable types like lists +=
changes the object's value, whereas for immutable types like tuples, strings and integers a new object is returned instead (a += b
becomes equivalent to a = a + b
).
对于同时支持__iadd__
和__add__
的类型,您必须小心使用哪种类型. a += b
将调用__iadd__
并对a
进行突变,而a = a + b
将创建一个新对象并将其分配给a
.它们是不同的操作!
For types that support both __iadd__
and __add__
you therefore have to be careful which one you use. a += b
will call __iadd__
and mutate a
, whereas a = a + b
will create a new object and assign it to a
. They are not the same operation!
>>> a1 = a2 = [1, 2]
>>> b1 = b2 = [1, 2]
>>> a1 += [3] # Uses __iadd__, modifies a1 in-place
>>> b1 = b1 + [3] # Uses __add__, creates new list, assigns it to b1
>>> a2
[1, 2, 3] # a1 and a2 are still the same list
>>> b2
[1, 2] # whereas only b1 was changed
对于不可变类型(没有__iadd__
的类型),a += b
和a = a + b
是等效的.这就是让您在不可变类型上使用+=
的原因,这似乎是一个奇怪的设计决定,除非您考虑到否则无法在数字等不可变类型上使用+=
!
For immutable types (where you don't have an __iadd__
) a += b
and a = a + b
are equivalent. This is what lets you use +=
on immutable types, which might seem a strange design decision until you consider that otherwise you couldn't use +=
on immutable types like numbers!
这篇关于为什么+ =在列表上表现异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!