3

のような右側の演算子を介して渡した後、numpy 配列のプロパティにアクセスするにはどうすればよい__rsub__ですか?

2 つの関数を定義する非常に単純なクラスを python で作成しました。

class test(object):
    def __sub__(self,  other):
        return other

    def __rsub__(self,  other):
        return other 

基本的に、彼らは同じことをするべきです。左側の演算子__sub__は期待どおりに機能しますが、numpy 配列は右側の演算子のプロパティから取り除かれているようです

from skimage import data
from skimage.color import rgb2gray
lena = data.lena()

grayLena = rgb2gray(lena)
t = test()

## overloaded - operator
left_hand = t - grayLena
print left_hand
# Output: 
#array([[ 0.60802863,  0.60802863,  0.60779059, ...,  0.64137412,
#    0.57998235,  0.46985725],
#  [ 0.60802863,  0.60802863,  0.60779059, ...,  0.64137412,
#    0.57998235,  0.46985725],
#  [ 0.60802863,  0.60802863,  0.60779059, ...,  0.64137412,
#    0.57998235,  0.46985725],
#  ..., 
#  [ 0.13746353,  0.13746353,  0.16881412, ...,  0.37271804,
#    0.35559529,  0.34377725],
#  [ 0.14617059,  0.14617059,  0.18730588, ...,  0.36788784,
#    0.37292549,  0.38467529],
#  [ 0.14617059,  0.14617059,  0.18730588, ...,  0.36788784,
#    0.37292549,  0.38467529]])

right_hand = grayLena - t
print right_hand
# Output:
# array([[0.6080286274509803, 0.6080286274509803, 0.6077905882352941, ...,
#   0.6413741176470589, 0.5799823529411765, 0.4698572549019608],
#  [0.6080286274509803, 0.6080286274509803, 0.6077905882352941, ...,
#   0.6413741176470589, 0.5799823529411765, 0.4698572549019608],
#  [0.6080286274509803, 0.6080286274509803, 0.6077905882352941, ...,
#   0.6413741176470589, 0.5799823529411765, 0.4698572549019608],
#  ..., 
#  [0.1374635294117647, 0.1374635294117647, 0.1688141176470588, ...,
#   0.3727180392156863, 0.35559529411764706, 0.34377725490196076],
#  [0.1461705882352941, 0.1461705882352941, 0.18730588235294118, ...,
#   0.3678878431372549, 0.37292549019607846, 0.3846752941176471],
#  [0.1461705882352941, 0.1461705882352941, 0.18730588235294118, ...,
#   0.3678878431372549, 0.37292549019607846, 0.3846752941176471]], dtype=object)

したがって、両方の操作の違いは__rsub__、dtype=object の配列を受け取ることです。この配列の dtype を設定するだけで、すべてうまくいきます。

ただし、 以外の戻り値でのみ機能します__rsub__。私の中には、__rsub__私が元に戻すことができないゴミしかありません。

npArray = np.array(other,  dtype=type(other))

タイプの 1D 配列を取得します (私の場合はフロート)。しかし、何らかの理由で形状情報が失われています。誰かがこれを行ったことがありますか、または配列の元のプロパティ (形状と型) にアクセスする方法を考えていますか?

4

1 に答える 1

1

の機械内の正確な制御フローndarrayが何であるかはわかりませんが、あなたの場合に何が起こっているかは多かれ少なかれ明確です。

ndarrayオブジェクトのメソッドに委任するのは、全体的な__rsub__減算操作ではなく、配列内の各アイテムからのオブジェクトの減算です。そして明らかに、オブジェクトのメソッドに操作を委任する必要がある場合object、何が返されるかに関係なく、returntypeはに設定されます。コードを少し変更するだけで確認できます。

class test(object):
    def __sub__(self,  other):
        return other

    def __rsub__(self,  other):
        return other if other != 1 else 666

In [11]: t = test()

In [12]: t - np.arange(4)
Out[12]: array([0, 1, 2, 3])

In [13]: np.arange(4) - t
Out[13]: array([0, 666, 2, 3], dtype=object)

この動作をオーバーライドする簡単な方法はないと思います。あなたは高いサブクラスを作っtestndarray__array_priority__てみて、メソッドを少し乱用することができます__array_wrap__

class test(np.ndarray):
    __array_priority__ = 100

    def __new__(cls):
        obj = np.int32([1]).view(cls)
        return obj

    def __array_wrap__(self, arr, context) :
        if context is not None :
            ufunc = context[0]
            args = context[1]
            if ufunc == np.subtract :
                if self is args[0] :
                    return args[1]
                elif self is args[1] :
                    return args[0]
        return arr

そして今:

>>> t = test()
>>> np.arange(4) - t
array([0, 1, 2, 3])
>>> t - np.arange(4)
array([0, 1, 2, 3])

だが:

>>> np.arange(4) + t
test([1, 2, 3, 4])
>>> t + np.arange(4)
test([1, 2, 3, 4])

1配列内のすべての値に内部を追加し、それを黙って破棄する操作を行っているため、少し無駄ですが、tそれをオーバーライドする方法は考えられません。

于 2013-03-11T19:56:45.533 に答える