python中的+=运算符似乎在列表上运行异常。谁能告诉我这是怎么回事?

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似乎以我希望事情表现的方式表现。
+=运算符称为“化合物赋值运算符”。

最佳答案

普遍的答案是+=尝试调用__iadd__特殊方法,如果该方法不可用,它将尝试使用__add__代替。因此,问题在于这些特殊方法之间的差异。
__iadd__特殊方法用于就地加法,即,它将对其作用的对象进行突变。 __add__特殊方法返回一个新对象,也用于标准+运算符。

因此,当在已定义+=的对象上使用__iadd__运算符时,将在适当位置修改该对象。否则,它将尝试使用普通的__add__并返回一个新对象。

这就是为什么对于诸如列表之类的可变类型+=会更改对象的值,而对于诸如元组,字符串和整数之类的不可变类型则会返回一个新对象(a += ba = a + b等效)。

因此,对于同时支持__iadd____add__的类型,您必须小心使用哪种类型。 a += b将调用__iadd__并对a进行突变,而a = a + b将创建一个新对象并将其分配给a。他们是不一样的操作!

>>> 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 += ba = a + b是等效的。这就是让您在不可变类型上使用+=的原因,这似乎是一个奇怪的设计决策,除非您考虑到否则您将无法在不可变类型(例如数字)上使用+=!

关于python - 为什么+ =在列表上表现异常?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48797161/

10-12 02:42