在Python中重载“+=”运算符?(__iadd__()方法)
在Python中,可以重写+=这个操作符吗?
4 个回答
15
除了重载 __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 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
的值是什么呢?
47
除了上面答案中正确提到的内容外,还需要明确说明,当你重写了 __iadd__
方法时,x += y
这个操作并不是在 __iadd__
方法结束时就结束了。
实际上,它是在 x = x.__iadd__(y)
这一步结束。换句话说,Python 会在你的 __iadd__
方法执行完后,把你实现的返回值赋给你“添加到”的那个对象。
这意味着你可以改变 x += y
左边的对象,导致最后的隐式步骤失败。想象一下,当你在给一个列表中的元素加东西时,会发生什么:
>>> x[1] += y # x 有两个元素
现在,如果你的 __iadd__
实现(也就是 x[1]
的一个方法)错误地或者故意地把列表的第一个元素(x[0]
)删除了,Python 会运行你的 __iadd__
方法,然后尝试把返回值赋给 x[1]
。但此时 x[1]
已经不存在了(它会变成 x[0]
),这就会导致一个 IndexError
错误。
或者,如果你的 __iadd__
方法在上面的例子中往 x
的开头插入了东西,那么你的对象会在 x[2]
,而不是 x[1]
,之前在 x[0]
的东西现在会在 x[1]
,并被赋值为 __iadd__
调用的返回值。
如果不理解发生了什么,导致的错误可能会让人头疼不已。
155
是的,可以重写 __iadd__
方法。下面是一个例子:
def __iadd__(self, other):
self.number += other.number
return self