[Numpy-discussion] Trouble subclassing ndarray

Elliot permafacture at gmail.com
Fri Apr 10 00:30:14 EDT 2015


Hi all,

Sorry if this is the wrong forum for a question like this.  

I'm trying to create an object with multiple inheritance, one of which is
from numpy.ndarray. The other gives it cacheable properties and defines a
__getattr__ to deliver the cached properties.  The initial instantiation is
successful, but ufuncs and slices cause an infinite recursion where the
__getattr__ function is used but the _cacheable attribute is not set (ie:
from __init__ )


I am using docs.scipy.org/doc/numpy/user/basics.subclassing.html as a
reference.
Here is code that shows my problem (python 2.7, numpy 1.8.2)

=====================

from __future__ import print_function
import numpy as np

class Cacheable(object):

    def __init__(self,*args,**kwargs):
        self._cacheable = {}

    def __getattr__(self,key):
       print("getting %s"%key)
       if key in self._cacheable:
         print("  found it")
         self._cacheable[key]()
         return self.__dict__[key] #if chache function does't update
         # data you're going to have a bad time
       else:
         raise AttributeError

    def _clear(self):
        '''clears derived properties'''
        for key in self._cacheable:
          if key in self.__dict__:
            del self.__dict__[key]


class BaseGeometry(np.ndarray,Cacheable):  
    '''Numpy array with extra attributes that are cacheable arrays'''

    def __new__(cls,input_array,dtype=np.float64,*args,**kwargs):
        # Input array is an already formed ndarray instance
        # We first cast to be our class type
        obj = np.asarray(input_array,dtype=dtype).view(cls)
        # Finally, we must return the newly created object:
        return obj

    def __init__(self,dims=None,dtype=np.float64,readonly=True):
        #TODO: sort through args and kwargs to make better 
        self.readonly=readonly
        if readonly:
           self.flags.writeable=False
        self.dims=dims
        self._dtype = dtype
        Cacheable.__init__(self)

    def writeable_copy(self):
        ret = np.copy(self)
        ret.flags.writeable = True
        return ret

    def __array_finalize_(self,obj):
       #New object, will be created in __new__
       print("array_finalize")
       if obj is None: return
       # created from slice or template
       print("finalizing slice")
       self._cacheable = getattr(obj, '_cacheable', None)


if __name__ == "__main__":
    n = 5 
    test = BaseGeometry(np.random.randint(-25,25,(n,2)))
    print("this works:",test._cacheable)
    broken = test[1:4] #interestingly, no problem here
    print(broken)  #infinite recursion 

===================

array_finalize is never called.  

output is:

this works: {}
getting _cacheable
getting _cacheable
getting _cacheable

[and on and on]

getting _cacheable
getting _cacheable
<repr(<__main__.BaseGeometry at 0x7fa42e2921b8>) failed: RuntimeError:
maximum recursion depth exceeded while calling a Python object>




--
View this message in context: http://numpy-discussion.10968.n7.nabble.com/Trouble-subclassing-ndarray-tp40176.html
Sent from the Numpy-discussion mailing list archive at Nabble.com.



More information about the NumPy-Discussion mailing list