【问题标题】:__radd__() method with Numpy Array as other, the Numpy Array was passed one by one__radd__() 方法以 Numpy Array 为 other,Numpy Array 被一一传递
【发布时间】:2019-09-26 15:47:05
【问题描述】:

我有一个类 (MyClass),其属性为 data,它是一个 Numpy 数组。我想允许这样的操作:

myclass3 = myclass1 + myclass2   
myclass3 = myclass1 + Numpy.ndarray  
myclass3 = Numpy.ndarray + myclass1  

所有这些操作将数据加在一起并返回一个新的 MyClass。所以通过定义add(),前两个很容易使用。但是对于最后一种情况,它的行为并不像我预期的那样,ndarray 用myclass1.data 逐个传递元素。

这就是我的意思。

import numpy as np
class MyClass:
    def __init__(self, data):
        self.data = data

    def __add__(self, other):
        print(other)
        if isinstance(other, MyClass):
            data = self.data + other.data
        else:
            data = self.data + other
        return MyClass(data)

    def __radd__(self, other):
        print(other)
        data = self.data + other
        return MyClass(data)

myclass1 = MyClass(np.arange(5))
myclass2 = MyClass(np.ones(5)) 
nparray = np.arange(5) + 10
alist = [1, 1, 1, 1, 1]

在所有的加法组合中,即使alist + myclass1也都可以,但是nparray + myclass1返回:

In __radd__: 10
In __radd__: 11
In __radd__: 12
In __radd__: 13
In __radd__: 14

发生的事情是 Numpy 数组的每个元素都被一个一个地而不是整体地传递到 radd 中。它返回五次,我将res 作为<class 'numpy.ndarray'> 而不是MyClass 对象。

那么我怎样才能允许Numpy.ndarray + MyClass 操作,其中整个 ndarray 将像 radd() 中的其他一样传入。

最好的问候, J

【问题讨论】:

  • 你为什么不从 ndarray 继承?
  • 这可能只是为了 __rdd__() 而工作,但我担心这会变得太混乱。此外,构造函数需要与 ndarray 内联,这将涉及重大的 API 更改。对于已经发布的包,我认为这是矫枉过正。

标签: python arrays numpy


【解决方案1】:

很遗憾,您对此无能为力。 alist + myclass1 失败,因此它会调用您的 __radd__ 函数,该函数按预期工作。但是,在nparray + myclass1 中,numpy 尝试通过广播来避免失败。所以,它相当于

for value in nparray.data:
    value + myclass

每次都会失败,只有到那时你的__radd__才会被调用。

【讨论】:

  • 那么有没有办法通过引发异常来阻止用户执行 nparray + myclass1 ?无论如何,在我的情况下不鼓励这样做,因为我正在处理音频数据,所以 nparray + myclass1 在不知道 nparray 的采样率的情况下是危险的。但是,我不想简单地在 __radd__() 处引发异常,因为 int + myclass1 是我想要的合法案例。
  • @J_yang:不,广播是自动的,它是在左添加失败之前调用的。在右添加中,您无法知道您得到的 int 是独立参数还是来自 numpy 广播数组。唯一的方法是从 np.array 继承(这并不简单,那个类中有太多的魔法)
  • 可能会检测到您是否被使用标量值调用并在这种情况下返回NotImplemented(假设您不想支持1 + myclass)。我想在某个时候 numpy 会放弃广播并让顶级 Python 代码尝试调用 __radd__ 方法本身。
  • @Blckknght:他想支持1 + myclass,这就是问题所在。 Numpy 在很大程度上建立在广播之上,在大多数情况下它是有益的,这是附带损害。删除它是非常不可能的
  • @Blckknght blue_note 是对的。我会牺牲这一点,以保持 1 + myclass 具有合法用例。
猜你喜欢
  • 2015-08-04
  • 2021-02-13
  • 2021-05-16
  • 1970-01-01
  • 2020-12-11
  • 2023-02-11
  • 2018-01-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多