在 NumPy 1.13+ 上,您可以使用 NumPy 特定的钩子来执行此操作,但一般情况下您不能让 __rsub__ 击败 __sub__ 方法。
__rsub__ 如果左操作数的__sub__ 无法处理该操作,但左操作数可以 处理该操作,则尝试。 NumPy 数组的 __sub__ 将接受任何 RHS 并执行广播减法。您对象的 __rsub__ 仅对广播减法中的各个操作起作用。
有一个非常有限的情况,首先尝试__rsub__,即如果 RHS 的类是 LHS 的类的子类。从技术上讲,您可以将numpy.ndarray 子类化,但这会带来很多 额外负担,并且对于numpy.matrix([[1]]) - obj 或其他子类仍然没有任何作用。
没有办法说“我希望我的__rsub__ 赢得一切”。它不存在,存在也没有意义,因为如果你试图减去两个都想声明其方法的对象会胜过一切?
所以这是一般情况。不过,特别是对于 NumPy,您可以挂钩到 numpy.ndarray.__sub__ 委托给的机制。
NumPy 数组将 __sub__ 委托给 NumPy ufunc 机器。那里有一堆奇怪的自定义选项,但我们对一个特定选项的特定用途感兴趣:通过在类级别将 __array_ufunc__ 设置为 None,您可以声明一个与 ufunc 不兼容的类。这意味着所有 NumPy 运算符重载都将返回 NotImplemented,让您的类处理操作。这会影响 所有 运算符和更多的东西,但以您可能想要的方式:
class MyClass:
__array_ufunc__ = None
def __rsub__(self, other):
print(type(other), other)
如果你想要比阻止所有 ufunc 更有针对性的东西,你可以实现一个实际的 __array_ufunc__ 方法,只处理 ufunc 是减法并且你的类的实例是 RHS 的情况:
class MyClass:
def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
if ufunc is not numpy.subtract:
return NotImplemented
if method != '__call__':
return NotImplemented
if len(inputs) != 2 or inputs[1] is not self:
return NotImplemented
if kwargs:
return NotImplemented
return self.__rsub__(inputs[0])
def __rsub__(self, other):
print(type(other), other)