gpt4 book ai didi

python - Python Numpy 中的数组和 __rmul__ 运算符

转载 作者:太空狗 更新时间:2023-10-29 20:49:14 24 4
gpt4 key购买 nike

在一个项目中,我创建了一个类,我需要在这个新类和一个真实的矩阵之间进行操作,所以我重载了__rmul__函数,这样

class foo(object):

aarg = 0

def __init__(self):
self.aarg = 1


def __rmul__(self,A):
print(A)
return 0

def __mul__(self,A):
print(A)
return 0

但是当我调用它时,结果不是我所期望的

A = [[i*j for i in np.arange(2)  ] for j in np.arange(3)]
A = np.array(A)
R = foo()
C = A * R

输出:

0
0
0
1
0
2

似乎该函数被调用了 6 次,每个元素调用一次。

相反,__mul__ 函数效果很好

C = R * A

输出:

[[0 0]
[0 1]
[0 2]]

如果 A 不是数组,而只是列表的列表,则两者都可以正常工作

A = [[i*j for i in np.arange(2)  ] for j in np.arange(3)]
R = foo()
C = A * R
C = R * A

输出

[[0, 0], [0, 1], [0, 2]]
[[0, 0], [0, 1], [0, 2]]

我真的希望我的 __rmul__ 函数也适用于数组(我原来的乘法函数不是可交换的)。我该如何解决?

最佳答案

行为是预期的。

首先,您必须了解像x*y 这样的操作是如何实际执行的。 python 解释器将首先 尝试计算x.__mul__(y)。如果此调用返回 NotImplemented,它将然后尝试计算 y.__rmul__(x)Exceptyx 类型的真子类时,在这种情况下,解释器将首先考虑 y.__rmul__(x ) 然后是 x.__mul__(y)

现在发生的事情是 numpy 根据他认为参数是标量还是数组来区别对待参数。

当处理数组时,* 执行逐个元素的乘法,而标量乘法将数组的所有条目乘以给定的标量。

在您的情况下,foo() 被 numpy 视为标量,因此 numpy 将数组的所有元素乘以 foo。此外,由于 numpy 不知道 foo 类型,它返回一个 dtype=object 的数组,所以返回的对象是:

array([[0, 0],
[0, 0],
[0, 0]], dtype=object)

注意:当您尝试计算乘积时,numpy 的数组返回NotImplemented,因此解释器调用 numpy 的数组__mul__ 方法,它执行我们所说的标量乘法。此时 numpy 将尝试将数组的每个条目乘以您的“标量”foo(),这就是您的 __rmul__ 方法被调用的地方,因为当使用 foo 参数调用它们的 __mul__ 时,数组返回 NotImplemented

显然,如果您将参数的顺序更改为初始乘法,您的 __mul__ 方法会立即被调用,您不会遇到任何问题。

因此,为了回答您的问题,处理此问题的一种方法是让 foo 继承自 ndarray,以便应用第二条规则:

class foo(np.ndarray):
def __new__(cls):
# you must implement __new__
# code as before

但是警告 subclassing ndarray isn't straightforward .此外,您可能还有其他副作用,因为现在您的类是一个 ndarray

关于python - Python Numpy 中的数组和 __rmul__ 运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38229953/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com