PEP 3141 introduces abstract base classes for different kinds of numbers to allow custom implementations.
I want to derive a class from numbers.Real
and calculate its sine value. Using pythons math
-module, this works fine. When I try the same in numpy, I get an error.
from numbers import Real
import numpy as np
import math
class Mynum(Real):
def __float__(self):
return 0.0
# Many other definitions
a = Mynum()
print("math:")
print(math.sin(a))
print("numpy:")
print(np.sin(a))
results in
math: 0.0 numpy: AttributeError: 'Mynum' object has no attribute 'sin' The above exception was the direct cause of the following exception: Traceback (most recent call last): [...] in <module> print(np.sin(a)) TypeError: loop of ufunc does not support argument 0 of type Mynum which has no callable sin method
It seems like numpy tries to call a sin
-method of its argument. To me, this is quite confusing since the standard data types (like float
) do not have such a method either, but np.sin
works on them.
Is there just some kind of hardcoded check for standard data types, and PEP 3141 is not supported? Or did I miss something in my class?
Because it is quite tedious to implement all required methods, here is my current code that works with the math
-module:
from numbers import Real
import numpy as np
import math
class Mynum(Real):
def __init__(self):
pass
def __abs__(self):
pass
def __add__(self):
pass
def __ceil__(self):
pass
def __eq__(self):
pass
def __float__(self):
return 0.0
def __floor__(self):
pass
def __floordiv__(self):
pass
def __le__(self):
pass
def __lt__(self):
pass
def __mod__(self):
pass
def __mul__(self):
pass
def __neg__(self):
pass
def __pos__(self):
pass
def __pow__(self):
pass
def __radd__(self):
pass
def __rfloordiv__(self):
pass
def __rmod__(self):
pass
def __rmul__(self):
pass
def __round__(self):
pass
def __rpow__(self):
pass
def __rtruediv__(self):
pass
def __truediv__(self):
pass
def __trunc__(self):
pass
a = Mynum()
print("math:")
print(math.sin(a))
print("numpy:")
print(np.sin(a))