Python 重载向量加法运算符 +

例子:

    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

 

你可能感兴趣的:(Python学习)