如何用一个numpy数组正确调用`__rsub__`?

时间:2019-10-16 08:32:01

标签: python numpy numpy-ndarray

请考虑以下代码段:

import numpy as np

class MyClass:
    def __rsub__(self, other):
        print(type(other), other)

obj = MyClass()
arr = np.ones(3)

arr - obj

我希望它能打印<class 'numpy.ndarray'> [1. 1. 1.]。 但实际上,似乎每个元素都调用__rsub__

<class 'float'> 1.0
<class 'float'> 1.0
<class 'float'> 1.0

是否可以告诉numpy我想要 first 行为,即将 entire 减法委派给MyClass? / p>

1 个答案:

答案 0 :(得分:2)

在NumPy 1.13+上,您可以使用NumPy特定的钩子来执行此操作,但是通常无法使S[5]击败__rsub__方法。


如果左操作数的__sub__无法处理该操作,则尝试

__rsub__,但是左操作数可以处理该操作。 NumPy数组的__sub__将接受任何RHS并执行广播减法。对象的__sub__仅对广播减法中的各个操作起作用。

在非常有限的情况下,首先尝试__rsub__,即RHS的类别是LHS的类别的子类别。从技术上讲,您可以细分__rsub__的子类,但这会带来很多的额外负担,而对于numpy.ndarray或其他子类仍然没有任何作用。

无法说“我希望我的numpy.matrix([[1]]) - obj赢得一切”。它不存在,并且存在也没有意义,因为如果您试图减去两个都想声明其方法的对象会击败一切,那会发生什么?


这就是一般情况。但是,专门针对NumPy,您可以使用__rsub__委托的机制。

NumPy数组将numpy.ndarray.__sub__委托给NumPy ufunc机制。那里有很多奇怪的自定义选项,但是我们对一个特定选项的特定用法感兴趣:通过在类级别将__array_ufunc__设置为__sub__,可以声明一个与ufunc不兼容的类。这意味着所有NumPy运算符重载都将返回None,让您的类处理该操作。这会影响 all 运算符和更多的东西,但是您可能会想要:

NotImplemented

如果您想要的东西比阻止所有ufunc更具针对性,则可以实现实际的class MyClass: __array_ufunc__ = None def __rsub__(self, other): print(type(other), other) 方法,并处理ufunc减法且类的实例为RHS的情况:

__array_ufunc__