Using multiplication operator mul for example, code
import numpy as np v = 1.0 a = float(v) b = np.float64(v) print(type(a*b), type(a.__mul__(b))) a = complex(v) b = np.complex128(v) print(type(a*b), type(a.__mul__(b))) produce the following output
<class 'numpy.float64'> <class 'float'> <class 'numpy.complex128'> <class 'complex'> Since <class 'float'>.__mul__(<class 'numpy.float64'>) and <class 'complex'>.__mul__(<class 'numpy.complex128'>) do not in fact return NotImplemented, according to Python documentation results should be <class 'float'> and <class 'complex'>, respectively.
Why is it not so? It seems binary arithmetic operators (+,-,*,/,etc) for builtin numeric types behave differently than their corresponding __op__() functions?
b.__rmul__(a)b.__rmul__(a)is correct in both cases. The question is whya.__mul__(b)is ignored when it does not returnNotImplemented.numpyobjects have a higher priority., and control the form of the '*'