4

この質問は、他の __rmul__ をクラスの __mul__ でオーバーライドするで尋ねられた内容に近いですが、これは数値データだけよりも一般的な問題であるという印象を受けています。@また、それは答えられておらず、この操作に行列乗算を使用したくありません。したがって、質問です。

スカラーと数値配列の乗算を受け入れるオブジェクトがあります。いつものように、左の乗算はmyobj()メソッドが使用されているため問題なく動作しますが、右の乗算では、NumPy はブロードキャスト ルールを使用し、要素ごとの結果を で返しますdtype=object

これには、配列のサイズに互換性があるかどうかを確認できないという副作用もあります。

したがって、質問は

__rmul__()要素ごとにブロードキャストして実行する代わりに、他のオブジェクトのを探すように numpy 配列を強制する方法はあり__mul__()ますか?

私の特定のケースでは、オブジェクトは MIMO (多入力多出力) 伝達関数行列 (または必要に応じてフィルター係数行列) であるため、行列の乗算は、線形システムの加算と乗算に関して特別な意味を持ちます。したがって、各エントリには SISO システムがあります。

import numpy as np

class myobj():
    def __init__(self):
        pass

    def __mul__(self, other):
        if isinstance(other, type(np.array([0.]))):
            if other.size == 1:
                print('Scalar multiplication')
            else:
                print('Multiplication of arrays')

    def __rmul__(self, other):
        if isinstance(other, type(np.array([0.]))):
            if other.size == 1:
                print('Scalar multiplication')
            else:
                print('Multiplication of arrays')

A = myobj()
a = np.array([[[1+1j]]])  # some generic scalar
B = np.random.rand(3, 3)

これらの定義では、次のコマンドは望ましくない動作を示します。

In [123]: A*a
Scalar multiplication

In [124]: a*A
Out[124]: array([[[None]]], dtype=object)

In [125]: B*A
Out[125]: 
array([[None, None, None],
       [None, None, None],
       [None, None, None]], dtype=object)

In [126]: A*B
Multiplication of arrays

In [127]: 5 * A

In [128]: A.__rmul__(B)  # This is the desired behavior for B*A
Multiplication of arrays
4

2 に答える 2

1

私は何が起こっているのかを実証しようとします。

In [494]: B=np.random.rand(3,3)

ベアボーン クラス:

In [497]: class myobj():
     ...:     pass
     ...: 
In [498]: B*myobj()
...

TypeError: unsupported operand type(s) for *: 'float' and 'myobj'

を追加__mul__

In [500]: class myobj():
     ...:     pass
     ...:     def __mul__(self,other):
     ...:         print('myobj mul')
     ...:         return 12.3
     ...: 
In [501]: B*myobj()
...
TypeError: unsupported operand type(s) for *: 'float' and 'myobj'
In [502]: myobj()*B
myobj mul
Out[502]: 12.3

を追加rmul:

In [515]: class myobj():
     ...:     pass
     ...:     def __mul__(self,other):
     ...:         print('myobj mul',other)
     ...:         return 12.3
     ...:     def __rmul__(self,other):
     ...:         print('myobj rmul',other)
     ...:         return 4.32
     ...: 
In [516]: B*myobj()
myobj rmul 0.792751549595306
myobj rmul 0.5668783619454384
myobj rmul 0.2196204913660168
myobj rmul 0.5474970289273348
myobj rmul 0.2079367474424587
myobj rmul 0.5374571198848628
myobj rmul 0.35748803226628456
myobj rmul 0.41306113085906715
myobj rmul 0.499598995529441
Out[516]: 
array([[4.32, 4.32, 4.32],
       [4.32, 4.32, 4.32],
       [4.32, 4.32, 4.32]], dtype=object)

B*myobj()は に与えられB、の各要素B.__mul__(myobj())に対して実行されます。myobj().__rmul__(i)B

myobj()*B変換されmyobj.__mul__(B)ます:

In [517]: myobj()*B
myobj mul [[ 0.79275155  0.56687836  0.21962049]
 [ 0.54749703  0.20793675  0.53745712]
 [ 0.35748803  0.41306113  0.499599  ]]
Out[517]: 12.3

In [518]: myobj().__rmul__(B)
myobj rmul [[ 0.79275155  0.56687836  0.21962049]
 [ 0.54749703  0.20793675  0.53745712]
 [ 0.35748803  0.41306113  0.499599  ]]
Out[518]: 4.32

myobjへの変換をオーバーライドするためにB*myobj()で何もすることはできませんB.__mul__(myobj())。操作をより詳細に制御する必要がある場合は、関数またはメソッドを使用します。通訳と戦うのは難しい。

于 2016-11-19T16:37:13.830 に答える