强制乘法使用__rmul __()而不是Numpy数组__mul __()或绕过广播


问题内容

这个问题与使用类的__mul__覆盖其他__rmul__中的问题很接近,但我的印象是,这是一个比数字数据更普遍的问题。同样也没有答案,我真的不想在@此操作中使用矩阵乘法。因此,这个问题。

我确实有一个接受标量和数值数组相乘的对象。与往常一样,因为myobj()使用了方法,所以左边的乘法效果很好,但是在右边的乘法中,NumPy使用广播规则,并使用给出元素的结果dtype=object

这也具有无法检查数组大小是否兼容的副作用。

因此,问题是

有没有一种方法可以强制numpy数组查找__rmul__()其他对象的,而不是广播并逐元素执行__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

问题答案:

默认情况下,NumPy假定未知对象(不是从ndarray继承)是标量,并且需要对任何NumPy数组的每个元素进行“向量化”乘法。

要自己控制操作,您需要设置__array_priority__(大多数向后兼容)或__array_ufunc__(仅适用于NumPy
1.13+)。例如:

class myworkingobj(myobj):
    __array_priority__ = 1000

A = myworkingobj()
B = np.random.rand(3, 3)
B * A  # Multiplication of arrays