是否可以在Python中覆盖+ =?
答案 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
class Resource(object):
class_counter = 0
def __init__(self):
self.id = self.class_counter
self.class_counter += 1
x = Resource()
y = Resource()
您希望x.id
,y.id
和Resource.class_counter
具有哪些价值?
答案 3 :(得分:5)
http://docs.python.org/reference/datamodel.html#emulating-numeric-types
例如,执行语句 x + = y,其中x是a的实例 具有__iadd __()方法的类, x .__ iadd __(y)被调用。