python 阻止接线员呼叫

python prevent operator call

我有一个 class CustomArray 类似于 numpy.ndarray。它重载了一堆算术运算符,如 __add____mul__ 等。由于人们很可能将它与 numpy 结合使用,我担心有时会调用 numpy.ndarray 运算符而不是 CustomArray。最糟糕的是它们实际上起作用并产生了一些不需要的结果。

a = np.array([1, 2, 3])
b = CustomArray([1, 2, 3])
c = a + b  # np.ndarray.__add__ will be called!

有什么办法可以防止这种情况发生吗?所以解释器要么引发错误,要么总是喜欢 CustomArray 运算符重载。

在 NumPy 1.13 中,有新的 __array_ufunc__ API。此 API 是 临时的 ,尚不能保证向后兼容性。

numpy.ndarray 将其运算符委托给 NumPy ufuncs,如果找到它,NumPy ufuncs 将委托给 __array_ufunc__ 以实现 ufunc 行为。此跳过的规则 numpy.ndarray.__array_ufunc__,因此如果您实现自己的 __array_ufunc__,在将您的实例与 NumPy 数组一起使用时,它将始终优先。

如果您想禁用对象上的所有 ufunc,可以在 class 上设置 __array_ufunc__ = None:

class CustomArray(...):
    __array_ufunc__ = None

或者,如果你想实现它,签名是

def __array_ufunc__(self, ufunc, method, *inputs, **kwargs)

您感兴趣的案例,

  • ufunc是ufunc对象(例如,numpy.add代表+),
  • method"__call__",
  • inputs 是元组 (left operand, right operand)
  • kwargs 为空。

对于更高级的案例,methodinputskwargs 可能有所不同,因此如果您不想处理这些案例,请 return NotImplemented

举个例子,如果你想用 NumPy 数组重载 +,你可以写

def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
    if ufunc is not numpy.add:
        return NotImplemented
    if method != "__call__":
        return NotImplemented
    if kwargs:
        return NotImplemented
    return my_addition_logic(*inputs)

您还需要实施 __add__