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

时间:2009-06-26 02:04:25

标签: python operators override

是否可以在Python中覆盖+ =?

4 个答案:

答案 0 :(得分:99)

是的,覆盖__iadd__方法。例如:

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

答案 1 :(得分:20)

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

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

这意味着可以改变x += y操作的左侧,以便最后的隐式步骤失败。考虑当您添加到列表中的内容时会发生什么:

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

现在,如果您的__iadd__实现(x[1]处的对象的方法)错误地或有意地从列表的开头删除了第一项(x[0]),那么Python将会然后运行你的__iadd__方法)&amp;尝试将其返回值分配给x[1]。哪个将不再存在(它将在x[0]),从而产生ÌndexError

或者,如果您的__iadd__在上述示例的x开头插入了某些内容,那么您的对象将位于x[2],而不是x[1],以及之前的任何内容x[0]现在位于x[1],并被赋予__iadd__调用的返回值。

除非人们理解正在发生的事情,否则导致的错误可能是一场噩梦。

答案 2 :(得分:12)

除了重载__iadd__(还记得返回自我!),您还可以回退__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 a.x, b.x
42 3
>>> old_id = id(a)
>>> a += b
>>> print a.x
45
>>> print old_id == id(a)
False

甚至trips up experts

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具有哪些价值?

答案 3 :(得分:5)

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

  

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