Если я немного расширю ваш класс, мы можем получить больше представления о том, когда используется __add__
и когда __radd__
:
class Test:
def __radd__(self, other):
print(f'r value: {other}, {type(other)}')
return f'{other}'
def __add__(self, other):
print(f'a value: {other}, {type(other)}')
return other+3
Со списком
In [285]: [1,2,3]+Test()
r value: [1, 2, 3], <class 'list'> # use Test.__radd__
Out[285]: '[1, 2, 3]'
In [286]: Test()+[1,2,3] # tries to use Test.__add__
a value: [1, 2, 3], <class 'list'>
....
<ipython-input-280-cd3f564be47a> in __add__(self, other)
5 def __add__(self, other):
6 print(f'a value: {other}, {type(other)}')
----> 7 return other+3
8
TypeError: can only concatenate list (not "int") to list
С массивом:
In [287]: np.arange(3)+Test() # use Test.__radd__ with each array element
r value: 0, <class 'int'>
r value: 1, <class 'int'>
r value: 2, <class 'int'>
Out[287]: array(['0', '1', '2'], dtype=object)
In [288]: Test()+np.arange(3)
a value: [0 1 2], <class 'numpy.ndarray'>
Out[288]: array([3, 4, 5]) # use Test.__add__ on whole array
Сам по себе, двойное использование Test.__add__
:
In [289]: Test()+Test()
a value: <__main__.Test object at 0x7fc33a5a7a20>, <class '__main__.Test'>
a value: 3, <class 'int'>
Out[289]: 6
Как я уже говорил, это может быть сложно разобрать __add__
v __radd__
делегирование и отделение этого от действия ndarray
.
add
с Test()
секундой дает тот же результат, что и [287]:
In [295]: np.add(np.arange(3),Test())
r value: 0, <class 'int'>
r value: 1, <class 'int'>
r value: 2, <class 'int'>
Out[295]: array(['0', '1', '2'], dtype=object)
np.add
с Test()
сначала отличается от [288] выше:
In [296]: np.add(Test(),np.arange(3))
a value: 0, <class 'int'>
a value: 1, <class 'int'>
a value: 2, <class 'int'>
Out[296]: array([3, 4, 5], dtype=object)