【问题标题】:python prevent operator callpython阻止操作员调用
【发布时间】:2018-05-25 11:18:19
【问题描述】:

我有一个类似于numpy.ndarray 的课程CustomArray。它重载了一堆算术运算符,如__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 运算符重载。

【问题讨论】:

  • 最近类似的问题(但没有答案):stackoverflow.com/questions/47600049/…
  • 不,没有。如果左边的操作数实现了该方法,它首先被执行。
  • @jonrsharpe mb 有一种方法可以修改 CustomArray 以便 numpy 产生一些合理的错误消息。
  • 不清楚您认为“一些合理的错误消息”。除非是NotImplemented,否则不会调用其他方法。

标签: python numpy operator-overloading operators


【解决方案1】:

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

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

如果要禁用对象上的所有 ufunc,可以在类上设置 __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__

【讨论】:

  • 由于某种原因无法使其工作,只有当我从 np.ndarray 子类化时它才能工作?
  • @DikobrAz:不,子类化 numpy.ndarray 并不是必需的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-13
相关资源
最近更新 更多