如何覆盖NumPy的ndarray和我的类型之间的比较?

And*_*ost 5 python numpy operators

在NumPy中,可以使用__array_priority__属性来控制作用于ndarray和用户定义类型的二进制运算符。例如:

class Foo(object):
  def __radd__(self, lhs): return 0
  __array_priority__ = 100

a = np.random.random((100,100))
b = Foo()
a + b # calls b.__radd__(a) -> 0
Run Code Online (Sandbox Code Playgroud)

但是,对于比较运算符而言,似乎不起作用。例如,如果将以下行添加到Foo,则永远不会从表达式中调用它a < b

def __rlt__(self, lhs): return 0
Run Code Online (Sandbox Code Playgroud)

我意识到这__rlt__并不是Python的特殊名称,但我认为它可能有用。我尝试了所有的__lt____le____eq____ne____ge____gt__有和没有前面r,加上__cmp__了,但是我永远无法与NumPy调用它们。

这些比较可以覆盖吗?

更新

为避免混淆,此处是NumPy行为的详细描述。首先,这是《 NumPy指南》书中所说的内容:

If the ufunc has 2 inputs and 1 output and the second input is an Object array
then a special-case check is performed so that NotImplemented is returned if the
second input is not an ndarray, has the array priority attribute, and has an
r<op> special method.
Run Code Online (Sandbox Code Playgroud)

我认为这是使+起作用的规则。这是一个例子:

import numpy as np
a = np.random.random((2,2))


class Bar0(object):
  def __add__(self, rhs): return 0
  def __radd__(self, rhs): return 1

b = Bar0()
print a + b # Calls __radd__ four times, returns an array
# [[1 1]
#  [1 1]]



class Bar1(object):
  def __add__(self, rhs): return 0
  def __radd__(self, rhs): return 1
  __array_priority__ = 100

b = Bar1()
print a + b # Calls __radd__ once, returns 1
# 1
Run Code Online (Sandbox Code Playgroud)

如您所见,如果没有__array_priority__,NumPy会将用户定义的对象解释为标量类型,并将操作应用于数组中的每个位置。那不是我想要的 我的类型类似于数组(但不应从ndarray派生)。

这是一个更长的示例,它显示了在定义所有比较方法时如何失败:

class Foo(object):
  def __cmp__(self, rhs): return 0
  def __lt__(self, rhs): return 1
  def __le__(self, rhs): return 2
  def __eq__(self, rhs): return 3
  def __ne__(self, rhs): return 4
  def __gt__(self, rhs): return 5
  def __ge__(self, rhs): return 6
  __array_priority__ = 100

b = Foo()
print a < b # Calls __cmp__ four times, returns an array
# [[False False]
#  [False False]]
Run Code Online (Sandbox Code Playgroud)

Tho*_*anz 0

我无法重现你的问题。正确的做法是使用__cmp__特殊方法。如果我写

import numpy as np

class Foo(object):
    def __radd__(self, lhs): 
        return 0

    def __cmp__(self, this):
        return -1

    __array_prioriy__ = 100

a = np.random.random((100,100))
b = Foo()
print a<b
Run Code Online (Sandbox Code Playgroud)

并在调试器中设置断点,执行在return -1.

顺便说一句:__array_prioriy__这里没有任何区别:你有一个错字!