【发布时间】:2020-04-22 16:33:19
【问题描述】:
我已经使用 python 3.7 几个月了,但我最近不得不切换到 python 2.7。由于我正在开发科学代码,因此我严重依赖使用中缀运算符 @ 来乘以 nd 数组。这个运算符是在 python 3.5 中引入的(请参阅here),因此,我不能在我的新设置中使用它。
显而易见的解决方案是将所有M1 @ M2 替换为numpy.matmul(M1, M2),这严重限制了我的代码的可读性。
我看到了这个hack,它定义了一个中缀类,允许通过重载or 和ror 运算符来创建自定义运算符。我的问题是:如何使用这个技巧使中缀 |at| 运算符像 @ 一样工作?
我尝试的是:
import numpy as np
class Infix:
def __init__(self, function):
self.function = function
def __ror__(self, other):
return Infix(lambda x, self=self, other=other: self.function(other, x))
def __or__(self, other):
return self.function(other)
def __call__(self, value1, value2):
return self.function(value1, value2)
# Matrix multiplication
at = Infix(lambda x,y: np.matmul(x,y))
M1 = np.ones((2,3))
M2 = np.ones((3,4))
print(M1 |at| M2)
当我执行这段代码时,我得到:
ValueError: operands could not be broadcast together with shapes (2,3) (3,4)
我想我知道什么是行不通的。当我只看M1|at时,我可以看到它是一个2*3的函数数组:
array([[<__main__.Infix object at 0x7faa1c0d6da0>,
<__main__.Infix object at 0x7faa1c0d6860>,
<__main__.Infix object at 0x7faa1c0d6828>],
[<__main__.Infix object at 0x7faa1c0d6f60>,
<__main__.Infix object at 0x7faa1c0d61d0>,
<__main__.Infix object at 0x7faa1c0d64e0>]], dtype=object)
这不是我所期望的,因为我希望我的代码将这个二维数组视为一个整体,而不是逐个元素...
有人知道我应该怎么做吗?
PS:我也考虑过使用this answer,但必须避免使用外部模块。
【问题讨论】:
-
这种事情更容易引起问题而不是解决问题。除了回到 3.x 之外,
numpy.matmul是您的最佳选择。 (NumPy 甚至不再支持 2.x。随着时间的推移,尝试在 2.x 上完成工作将会遇到越来越多的兼容性问题。) -
感谢您的回答。回到 2.x 不是一个选择,因为我现在在我公司拥有和管理的虚拟机上开发代码。我想我会按照你的建议使用
numpy.matmul,但这可能会让人不舒服...... -
示例问题:
|对您的需求有错误的优先级。A + B@C表示你认为它的作用,但A + B|at|C表示(A+B)|at|C即使你得到了这个工作。使用matmul,至少一旦您在脑海中解析代码,就清楚什么是什么的参数。 -
看看是否可以在 VM 中获取 Python 3。 (您不需要 root 来执行此操作。)
标签: python numpy operators python-2.x matrix-multiplication