在Python中覆盖“+ =”? (__iadd __()方法)

是否有可能重写+ =在Python中?

是的,覆盖__iadd__方法。 例:

 def __iadd__(self, other): self.number += other.number return self 

除了重载__iadd__ (记得要返回self!)之外,还可以使用__add__ ,因为x + = y将像x = x + y一样工作。 (这是+ =操作符的缺陷之一。)

 >>> class A(object): ... def __init__(self, x): ... self.x = x ... def __add__(self, other): ... return A(self.x + other.x) >>> a = A(42) >>> b = A(3) >>> print ax, bx 42 3 >>> old_id = id(a) >>> a += b >>> print ax 45 >>> print old_id == id(a) False 

它甚至绊倒了专家 :

 class Resource(object): class_counter = 0 def __init__(self): self.id = self.class_counter self.class_counter += 1 x = Resource() y = Resource() 

你期望x.idy.idResource.class_counter有什么值?

除了上面答案中正确给出的内容之外,值得明确的说明,当__iadd__被覆盖时, x += y操作不会以__iadd__方法结束而结束。

相反,它以x = x.__iadd__(y) 。 换句话说,在实现完成后,Python会将__iadd__实现的返回值分配给您要“添加到”的对象。

这意味着可以对x += y操作的左侧进行变异,以便最终的隐式步骤失败。 考虑当你添加到列表中的东西时会发生什么:

>>> x[1] += y # x has two items

现在,如果你的__iadd__实现( x[1]的一个对象的方法)错误地或有意地从列表的开始处移除了第一个项目( x[0] ),Python将运行你的__iadd__方法)尝试将其返回值分配给x[1] 。 这将不再存在(它将在x[0] ),导致一个ÌndexError

或者,如果你的__iadd__在上面的例子的x的开头插入了一些东西,你的对象将在x[2] ,而不是x[1] ,并且现在在x[0]处的任何东西现在将在x[1]和被分配了__iadd__调用的返回值。

除非人们明白发生了什么事情,否则造成的错误可能是一个噩梦。

http://docs.python.org/reference/datamodel.html#emulating-numeric-types

例如,要执行语句x + = y,其中x是具有__iadd __()方法的类的实例,则调用x .__ iadd __(y)。