-
-
Notifications
You must be signed in to change notification settings - Fork 10.9k
8000 Register class a subclass of NumPy array #4072
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Lots of code also uses isinstance to check if an object actually is an Most code should either call asarray or just start using the object, if it
|
I don't think ndarray was designed for duck typing and |
Thanks for taking the time to answer this. For the purpose that I have described, there is no real difference between guarding with I wrote a small toy code to demonstrate the problem: import numpy as np
class S(np.ndarray):
pass
class W(object):
def __init__(self, value):
self.value = value
def __getattr__(self, name):
return getattr(self.value, name)
def __getitem__(self, key):
return self.value.__getitem__(key)
a = np.arange(1, 10)
w = W(np.arange(1, 10))
s = S(a.shape)
s[:] = np.arange(1, 10)
func = np.diff
da = func(a)
dw = func(w)
ds = func(s)
print('Numpy version', np.__version__)
print('Array', np.asanyarray(a), da.shape, type(da))
print('Wrapping', np.asanyarray(a), dw.shape, type(dw))
print('Subclassing', np.asanyarray(a), ds.shape, type(ds)) The output is:
Notice that for I also understand that I can roll my own |
@charris registering using the mechanisms provided by the Abstract Base Class module is not the same as duck typing. |
Not sure I understand, but if your wrapping class implements |
Depends what do you mean by work. It does return the right values, but not the right class. Just replace the last 4 lines of the code above by: print('Numpy version', np.__version__)
print('Array', type(np.asanyarray(a)), da.shape, type(da))
print('Wrapping', type(np.asanyarray(w)), dw.shape, type(dw))
print('Subclassing', type(np.asanyarray(s)), ds.shape, type(ds)) The output is:
Maybe I am forgetting to define something? My interpretation is that because |
I would not turn None of this will solve your wrapper problem, though. You need to implement |
@rkern I am not sure that I follow. What I am suggesting is the ability to register an unrelated class as a subclass of Additionally, def __array_wrap__(self, out_arr, context=None):
return self.value.__array_wrap__(out_arr, context) and you will get the same result. |
I am saying that registering a non-subclass as an implementation of You might be able to make good, small ABCs that are subsets of the Python-side As for implementing |
@rkern Thanks for taking the time to answer the idea about registering But there is one thing that I still do not get about Changing the code to: def __getattr__(self, name):
print(name)
return getattr(self.value, name)
|
Yes, sorry. |
Then it seems that the only real option is to subclass. |
I think what you're seeing here is |
Some packages use
isinstance(x, numpy.ndarray)
to check if a given object can be used as anndarray
. This fails (of course) for object from classes derived fromobject
even if they implement all numpy methods and attributes. It would be good to be able to register a class as a ndarray subclass usingabc
The text was updated successfully, but these errors were encountered: