6

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

ただし、同じことが比較演算子では機能しないようです。たとえば、次の行を に追加するFooと、式から呼び出されることはありませんa < b

def __rlt__(self, lhs): return 0

これは実際には Python の特別な名前ではないことに気付きました__rlt__が、うまくいくかもしれないと思いました。__lt__, __le__, __eq__, ,__ne__のすべてを前に , plusを付けて、__ge__または付けずに試してみましたが、NumPy にそれらのいずれかを呼び出すことはできませんでした。__gt__r__cmp__

これらの比較は上書きできますか?

アップデート

混乱を避けるために、ここでは 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.

これが + を機能させるルールだと思います。次に例を示します。

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

ご覧のとおり、 がない__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]]
4

2 に答える 2

2

これなら自分でも答えられそうです。 np.set_numeric_ops次のように使用できます。

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

def override(name):
  def ufunc(x,y):
    if isinstance(y,Foo): return NotImplemented
    return np.getattr(name)(x,y)
  return ufunc

np.set_numeric_ops(
    ** {
        ufunc : override(ufunc) for ufunc in (
            "less", "less_equal", "equal", "not_equal", "greater_equal"
          , "greater"
          )
    }
  )

a = np.random.random((2,2))
b = Foo()
print a < b
# 4
于 2013-01-31T23:23:48.730 に答える
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

デバッガーでブレークポイントを設定すると、実行はで停止しますreturn -1

ところで:__array_prioriy__ここでは何の違いもありません:タイプミスがあります!

于 2013-01-31T06:20:04.667 に答える