Python: How to extend a huge class with minimum lines of code? Python: How to extend a huge class with minimum lines of code? numpy numpy

Python: How to extend a huge class with minimum lines of code?


As explained in the docs you could add your own methods to np.ndarray doing:

import numpy as npclass Ludmo(np.ndarray):     def sumcols(self):        return self.sum(axis=1)    def sumrows(self):        return self.sum(axis=0)    def randomize(self):        self[:] = np.random.rand(*self.shape)

and then creating the instances using the np.ndarray.view() method:

a = np.random.rand(4,5).view(Ludmo)

And use the __array_finalize__() method to define new attributes:

def __array_finalize__(self, arr):    self.foo = 'foo'


Since you ask about a generic solution, here's a generic wrapper class that you can use: (from http://code.activestate.com/recipes/577555-object-wrapper-class/ )

class Wrapper(object):    '''    Object wrapper class.    This a wrapper for objects. It is initialiesed with the object to wrap    and then proxies the unhandled getattribute methods to it.    Other classes are to inherit from it.    '''    def __init__(self, obj):        '''        Wrapper constructor.        @param obj: object to wrap        '''        # wrap the object        self._wrapped_obj = obj    def __getattr__(self, attr):        # see if this object has attr        # NOTE do not use hasattr, it goes into        # infinite recurrsion        if attr in self.__dict__:            # this object has it            return getattr(self, attr)        # proxy to the wrapped object        return getattr(self._wrapped_obj, attr)

the way this works is:

when e.g. skicit would call ludmo.data python actually callsludmo.__getattribute__('data')if ludmo doesn't have the 'data' attribute, python will callludmo.__getattr__('data')

by overridding the __getattr__ function you intercept this call, check if your ludmo has the data attribute (again, you could get into recursion otherwise), and send the call to your internal object. So you should have covered every possible call to your internal numpy object.

update:You would also have to implement __setattr__ the same way, or you would get this

>>> class bla(object):...  def __init__(self):...   self.a = 1...  def foo(self):...   print self.a...>>> d = Wrapper(bla())>>> d.a1>>> d.foo()1>>> d.a = 2>>> d.a2>>> d.foo()1

and you probably also want to set a new metaclass that intercepts calls to magic functions of new style classes (for full class see https://github.com/hpcugent/vsc-base/blob/master/lib/vsc/utils/wrapper.py for info see How can I intercept calls to python's "magic" methods in new style classes?)however, this is only needed if you still want to be able to access x.__name__ or x.__file__ and get the magic attribute from the wrapped class, and not your class.

# create proxies for wrapped object's double-underscore attributes    class __metaclass__(type):        def __init__(cls, name, bases, dct):            def make_proxy(name):                def proxy(self, *args):                    return getattr(self._obj, name)                return proxy            type.__init__(cls, name, bases, dct)            if cls.__wraps__:                ignore = set("__%s__" % n for n in cls.__ignore__.split())                for name in dir(cls.__wraps__):                    if name.startswith("__"):                        if name not in ignore and name not in dct:                            setattr(cls, name, property(make_proxy(name)))