I have the following unexpected behaviour
import numpy as np
class Test:
def __radd__(self, other):
print(f'value: {other}')
[1,2,3] + Test()
# prints: value: [1,2,3]
np.array([1,2,3]) + Test()
# prints
# value: 1
# value: 2
# value: 3
I would expect the second addition to behave in the same way as the first one, but it doesn't. The only logical explanation I can see is that the numpy +
operator somehow iterates over the arguments first, and tries to add each one of them to Test()
, and the second addition (int + Test)
falls back to the Test.__radd__
So
a + b
work in numpynp.add(a, b)
?sum() function is available in the NumPy package of Python. This function is used to compute the sum of all elements, the sum of each row, and the sum of each column of a given array. Essentially, this sum ups the elements of an array, takes the elements within a ndarray, and adds them together.
To add the two arrays together, we will use the numpy. add(arr1,arr2) method. In order to use this method, you have to make sure that the two arrays have the same length. If the lengths of the two arrays are not the same, then broadcast the size of the shorter array by adding zero's at extra indexes.
NumPy aims to provide an array object that is up to 50x faster than traditional Python lists. The array object in NumPy is called ndarray , it provides a lot of supporting functions that make working with ndarray very easy. Arrays are very frequently used in data science, where speed and resources are very important.
sum receives an array of booleans as its argument, it'll sum each element (count True as 1 and False as 0) and return the outcome. for instance np. sum([True, True, False]) will output 2 :) Hope this helps.
This is because of NumPy 'broadcasting'.
Your explanation is pretty much correct as you can see in the docs for np.add
.
Notes
Equivalent to x1 + x2 in terms of array broadcasting.
I find this makes a little more sense if you play around with NumPy and see how np.array
differs from the built-in list.
Python 3.5.2 (default, Jul 6 2016, 16:37:16)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help.
In [1]: import numpy as np
In [2]: [1, 2, 3] + [1, 2, 3]
Out[2]: [1, 2, 3, 1, 2, 3]
In [3]: np.array([1, 2, 3]) + np.array([1, 2, 3])
Out[3]: array([2, 4, 6])
Looking at the sourcecode here for the NDArrayOperatorsMixin
which implements the special methods for almost all of Python's builtin operators defined in the `operator` module
. It looks like __add__, __radd__, __iadd__
are all set to the .add
umath function. But I'm not sure if the actual ndarray
makes use of the mix-in, I think you'd have to dig through the C code to figure out how that's handled.
If I expand your class a bit we may get more of an idea of when __add__
is used, and when __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
With a list
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
With an array:
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
With itself, a double use of Test.__add__
:
In [289]: Test()+Test()
a value: <__main__.Test object at 0x7fc33a5a7a20>, <class '__main__.Test'>
a value: 3, <class 'int'>
Out[289]: 6
As I commented it can be tricky sorting out the __add__
v __radd__
delegation, and separating that from ndarray
action.
add
with Test()
second gives the same output as [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
with Test()
first is different from [288] above:
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With