3

在python 3.5中,引入了@运算符进行矩阵乘法运算,跟在PEP465后面。这是通过例如在numpy作为matmul operator使矩阵乘法运算符@为numpy中的标量运算

然而,由于提出的PEP,当一个标量操作数称为numpy的运营商抛出异常:

>>> import numpy as np 
>>> np.array([[1,2],[3,4]]) @ np.array([[1,2],[3,4]]) # works 
array([[ 7, 10], 
     [15, 22]]) 
>>> 1 @ 2            # doesn't work 
Traceback (most recent call last): 
    File "<input>", line 1, in <module> 
TypeError: unsupported operand type(s) for @: 'int' and 'int' 

这对我来说是一个真正的关断,因为我实现数字信号处理算法应该适用于标量和矩阵。这两种情况下的方程式在数学上完全等价,这并不奇怪,因为“1-D x 1-D矩阵乘法”等价于标量乘法。然而,目前的状态迫使我编写重复的代码,以便正确处理这两种情况。

因此,鉴于目前的状态并不令人满意,是否有任何合理的方法可以使@运营商适用于标量?我想过为标量数据类型添加一个自定义的__matmul__(self, other)方法,但考虑到涉及的内部数据类型的数量,这似乎很麻烦。我是否可以将numpy数组数据类型的__matmul__方法的实现更改为不引发1x1数组操作数的异常?

而且,在这个设计决策背后的理由是什么?从我的头顶来看,我想不出有什么令人信服的理由不要为标量实现这个操作符。

+0

'[1] @ [2]'怎么样?标量已经有'*'为什么要复制它。 – furas

+4

听起来像真正的问题是你的代码有时会返回标量,有时会返回矩阵。为什么不重构,以便您的代码返回1 x 1矩阵而不是标量?或者编写一个快速函数,该函数采用矩阵或标量并返回该矩阵或带有标量的1x1矩阵 –

+0

为什么不能使用try - except例程? – Jalo

回答

1

由于ajcr建议,您可以通过强制对象上的一些最小维数相乘来解决此问题。有两个合理的选项:atleast_1datleast_2d,它们在@返回的类型方面有不同的结果:标量与1乘1的二维数组。

x = 3 
y = 5 
z = np.atleast_1d(x) @ np.atleast_1d(y) # returns 15 
z = np.atleast_2d(x) @ np.atleast_2d(y) # returns array([[15]]) 

然而:

  • 使用atleast_2d将导致一个错误,如果x和y是一维阵列,否则将被正常地乘以
  • 使用atleast_1d将导致要么是该产品标量或矩阵,你不知道哪个。
  • 这两个都比np.dot(x, y)更详细,它可以处理所有这些情况。

此外,atleast_1d版本还存在相同的缺陷,也可以通过标量@ scalar =标量共享:您不知道可以对输出做什么。将z.Tz.shape抛出一个错误?这些适用于1乘1的矩阵,但不适用于标量。在Python的设置中,我们不能忽视标量和1乘1阵列之间的区别,同时也不会放弃后者所具有的所有方法和属性。