Если я расширю ваш класс с помощью метода __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)
и попробую несколько вызовов 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]),)}
, показывающихинформация, которую получает ваш класс.Очевидно, вы можете делать то, что вы хотите.Может вернуть NotImplemented
.Я полагаю, что в вашем случае он может применить первый аргумент к вашему self.value
или выполнить какой-либо специальный расчет.
Например, если я добавлю
val = args[0].__call__(self.value)
return toto(val, self.name)
, я получу:
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
Однако, если я помещаю объект в массив, я все равно получаю ошибку метода
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'
Видимо ufunc
в массиве объекта dtype выполняет итерации по элементам массива, ожидая использовать«соответствующий» метод.Для np.add
(+) он ищет метод __add__
.Для np.exp
он ищет метод exp
.Это __array_ufunc__
не называется.
Так что похоже, что оно предназначено больше для подкласса ndarray
или чего-то подобного.Вы, я думаю, пытаетесь реализовать класс, который может работать как элементы массива dtype объекта.