例子:
def __add__(self, other):
try:
pairs = itertools.zip_longest(self, other, fillvalue=0.0)
return Vector(a + b for a, b in pairs)
except TypeError:
return NotImplemented
pairs 是个生成器,它会产生(a,b)形式的元组,其中a来自self,b来自other,如果self和other的长度不同,使用fillvalue填充较短的那个可迭代对象。然后可以使用生成器表达式计算pairs中的各个元素之和。
>>> v1 + (10, 20, 30)
Vector([13.0, 24.0, 35.0])
>>> v2d = Vector2d(1, 2)
>>> v1 + v2d
Vector([4.0, 6.0, 5.0])
上面两个 + 是使用了 __add__ 方法,__add__使用了zip_logest(),它能处理任何迭代对象,而且构建新的vector实例的生成器表达式仅仅是把zip_longest()生成的值对相加(a+b),因此可以使用任何生成数字元素的可迭代对象。
>>> v1 = Vector([3,4,5])
>>> (10, 20, 30) + v1
TypeError:can only concatenate tuple (not 'Vector') to tuple
>>> v2d = Vector2d(1, 2)
>>> v2d + v1
TypeError:unsupported operand type(s) for +:'Vector2d' + 'Vector'
但是对调操作数,混合类型加载就会失败。
为了支持涉及不同类型的运算,Python 为中缀运算符特殊方法提供了特殊的分派机制。对于表达式 a+b 来说,解释器会执行以下几步:
1.如果 a 有 __add__ 方法,而且返回值不是 NotImplemented,调用 a.__add__(b),然后返回结果。
2.如果 a 没有 __add__ 方法,或者调用 __add__ 方法返回 NotImplemented,检查 b 有没有 __radd__ 方法,如果有,而且没有返回 NotImplemednted,调用 b.__radd__(a),然后返回结果。
3.如果 b 没有 __radd__ 方法,或者调用 __radd__ 方法返回 NotImplemented,抛出 TypeError,并在错误消息中指明操作数类型不支持。
__radd__ 是 __add__ 的反向版本。这是一种后备机制,如果左操作数没有实现 __add__ 方法,或者实现了,但是返回 NotImplemened 表明他不知道如何处理右操作数,那么 Python 会调用 __radd__ 方法。
实现如下:
def __add__(self, other):
try:
pairs = itertools.zip_longest(self, other, fillvalue=0.0)
return Vector(a + b for a, b in pairs)
except TypeError:
return NotImplemented
def __radd__(self, other):
return self + other