I'm just curious about how numpy implements its scalar multiplication. In my understanding,
x * y
calls the __mul__
method of x, x.__mul__(y)
.
How would this work with this code:
x = 6
y = np.array([1,2])
print(x * y)
Wouldn't the code call x.__mul__(y)
? And since x is not a numpy variable, how does numpy have any control over how this behaves?
CodePudding user response:
When Python encounters x * y
it will indeed first call x.__mul__(y)
(1). Any such method may return NotImplemented
if it doesn't know how to handle the operand it received. This is what x.__mul__(y)
does :
>>> x = 6
>>> y = np.array([1, 2])
>>> x.__mul__(y)
NotImplemented
Then, as a next step, Python calls the reflected operands method __rmul__
, i.e. y.__rmul__(x)
:
>>> y.__rmul__(x)
array([ 6, 12])
So in this second step, it is up to the np.ndarray
class to determine the outcome of this operation (2).
This can also be visualized with the help of a custom test class:
>>> class Test:
... def __rmul__(self, other):
... print('__rmul__', self, other)
...
>>> x = 1
>>> y = Test()
>>> x.__mul__(y)
NotImplemented
>>> x * y
__rmul__ <__main__.Test object at 0x7f46c6acb668> 1
(1) Unless type(y)
is a subclass of type(x)
in which case y.__rmul__(x)
takes precedence over x.__mul__(y)
.
(2) If both methods, x.__mul__
and y.__rmul__
, return NotImplemented
then a TypeError
is raised.