Python Function Decorators 3: Input Based Caching

Below you can find an input based cache system implemented as a Python function decorator:

########################################################################
class InputBasedCachedMethod(object):
    """caches the result of a class method inside the instance based on the input
    """
    
    
    
    #----------------------------------------------------------------------
    def __init__(self, method):
        # record the unbound-method and the name
        #print "running __init__ in InputBasedCachedMethod"
        
        self._method = method
        self._name = method.__name__
        self._obj = None
        
        
        
    #----------------------------------------------------------------------
    def __get__(self, inst, cls):
        """use __get__ just to get the instance object
        """
        #print "running __get__ in InputBasedCachedMethod"
        
        self._obj = inst
        if not hasattr( self._obj, self._name + "._outputData" ):
            #print "creating the data"
            setattr ( self._obj, self._name + "._outputData", list() )
            setattr ( self._obj, self._name + "._inputData", list() )
            #print "finished creating data"
            
        return self
    
    
    
    #----------------------------------------------------------------------
    def __call__(self, *args, **keys):
        """for now it uses only one argument
        """
        #print "running __call__ in InputBasedCachedMethod"
        
        outputData = getattr( self._obj, self._name + "._outputData" )
        inputData = getattr( self._obj, self._name + "._inputData" )
        
        # combine args and keys
        argsKeysCombined = list()
        argsKeysCombined.append( args )
        argsKeysCombined.append( keys )
        
        if (not argsKeysCombined in inputData) or outputData == None:
            #print "calculating new data"
            data = self._method(self._obj, *args, **keys)
            inputData.append( argsKeysCombined )
            outputData.append( data )
            setattr( self._obj, self._name + "._inputdata", inputData )
            setattr( self._obj, self._name + "._outputData", outputData )
            
            return data
        else:
            #print "returning cached data"
            return outputData[ inputData.index( argsKeysCombined ) ]
    
    
    
    #----------------------------------------------------------------------
    def __repr__(self):
        """Return the function's repr
        """
        #print "running __repr_ in InputBasedCachedMethod"
        objectsRepr = str(self._obj)
        objectsName = objectsRepr.split(' ')[0].split('.')[-1]
        cachedObjectsRepr = ''
        return cachedObjectsRepr


Edit 1: Edited the cache class, now it supports both arguments and keyword arguments, and I didn't delete the lines that has print commands, so you can uncomment the lines to see which one of the methods runs when

Comments