[英]How to overide numpy ufunc with __array_ufunc__
I'm trying to implement numpy's ufunc to work with a class, using the __array_ufunc__ method introduced in numpy v1.13. 我正在尝试使用numpy v1.13中引入的__array_ufunc__方法来实现numpy的ufunc来处理类。
To simplify, here's what the class could look like : 为简化起见,这是类的外观:
class toto():
def __init__(self, value, name):
self.value = value
self.name = name
def __add__(self, other):
"""add values and concatenate names"""
return toto(self.value + other.value, self.name + other.name)
def __sub__(self, other):
"""sub values and concatenate names"""
return toto(self.value - other.value, self.name + other.name)
tata = toto(5, "first")
titi = toto(1, "second")
Now if I try to apply np.add between these two, I get the expected result, as np.add relies on add . 现在,如果我尝试在这两者之间应用np.add,我会得到预期的结果,因为np.add依赖于add 。 But if I call say np.exp, I get an error as expected :
但如果我打电话说np.exp,我会收到预期的错误:
>>> np.exp(tata)
AttributeError: 'toto' object has no attribute 'exp'
Now what I would like to do is to "override" all numpy ufuncs to work smoothly with this class without having to redefine every methods (exp(self), log(self), ...) in the class. 现在我想做的是“覆盖”所有numpy ufunc,以便在这个类中顺利运行,而无需在类中重新定义每个方法(exp(self),log(self),...)。
I was planning to use numpy ufunc's [__array_ufunc__] 1 to do this, but I don't really understand the doc as it doesn't provide a simple exemple of implementation. 我打算使用numpy ufunc的[__array_ufunc__] 1来做这件事,但我并不真正理解这个文档,因为它没有提供一个简单的实现例子。
If anyone has had any experience with this new functionnality that looks promising, could you provide a simple example ? 如果有人对这个看起来很有前景的新功能有任何经验,你能提供一个简单的例子吗?
If I extend your class with a __array_ufunc__
method (and __repr__
): 如果我有一个扩展您的类
__array_ufunc__
方法(和__repr__
):
class toto():
def __init__(self, value, name):
self.value = value
self.name = name
def __add__(self, other):
"""add values and concatenate names"""
return toto(self.value + other.value, self.name + other.name)
def __sub__(self, other):
"""sub values and concatenate names"""
return toto(self.value - other.value, self.name + other.name)
def __repr__(self):
return f"toto: {self.value}, {self.name}"
def __array_ufunc__(self, *args, **kwargs):
print(args)
print(kwargs)
And try some ufunc
calls: 并尝试一些
ufunc
调用:
In [458]: np.exp(tata)
(<ufunc 'exp'>, '__call__', toto: 5, first)
{}
In [459]: np.exp.reduce(tata)
(<ufunc 'exp'>, 'reduce', toto: 5, first)
{}
In [460]: np.multiply.reduce(tata)
(<ufunc 'multiply'>, 'reduce', toto: 5, first)
{}
In [461]: np.exp.reduce(tata,axes=(1,2))
(<ufunc 'exp'>, 'reduce', toto: 5, first)
{'axes': (1, 2)}
In [463]: np.exp.reduce(tata,axes=(1,2),out=np.arange(3))
(<ufunc 'exp'>, 'reduce', toto: 5, first)
{'axes': (1, 2), 'out': (array([0, 1, 2]),)}
That shows the information that your class receives. 这显示了您的班级收到的信息。 Evidently you can do what you want that.
显然你可以做你想做的事。 It can return
NotImplemented
. 它可以返回
NotImplemented
。 I suppose in your case it could apply the first argument to your self.value
, or do some custom calculation. 我想在你的情况下它可以将第一个参数应用于你的
self.value
,或者做一些自定义计算。
For example if I add 例如,如果我添加
val = args[0].__call__(self.value)
return toto(val, self.name)
I get: 我明白了:
In [468]: np.exp(tata)
(<ufunc 'exp'>, '__call__', toto: 5, first)
{}
Out[468]: toto: 148.4131591025766, first
In [469]: np.sin(tata)
(<ufunc 'sin'>, '__call__', toto: 5, first)
{}
Out[469]: toto: -0.9589242746631385, first
However if I put the object in an array, I still get the method error 但是,如果我将对象放在一个数组中,我仍然会得到方法错误
In [492]: np.exp(np.array(tata))
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-492-4dc37eb0ffe3> in <module>
----> 1 np.exp(np.array(tata))
AttributeError: 'toto' object has no attribute 'exp'
Apparently ufunc
on an object dtype array iterates on the elements of the array, expecting to use a 'relevant' method. 显然
ufunc
上的数组的元素的对象D型细胞阵列进行迭代,希望使用一个“相关”方法。 For np.add
(+) it looks for the __add__
method. 对于
np.add
(+),它查找__add__
方法。 For np.exp
it looks for an exp
method. 对于
np.exp
它查找exp
方法。 This __array_ufunc__
isn't called. 这个
__array_ufunc__
没有被调用。
So it looks like it's intended more for a subclass of ndarray
, or something equivalent. 所以它看起来更像是
ndarray
的子类,或类似的东西。 You, I think, are trying to implement a class that can work as elements of an object dtype array. 我认为,您正在尝试实现一个可以作为对象dtype数组元素的类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.