I've been writing a class and I've noticed that one of its methods may could create a lot of overhead to our file server when it is used often. And its result was not changing so often. So trying to get all the data over and over again is something I should avoid.
I've decided to create some kind of caching system to overcome this problem. I've changed the function so it was caching its own result, and it was not trying to get the data over and over again before some definite time is passes. It was working very nice. But later on I've noticed several other functions those had to have this functionality.
So I've decided to use a decorator that decorates the functions with that ability. Here is the decorator:
You can use that anywhere you want, but beware that the caching is time dependent, not input dependent.
I've decided to create some kind of caching system to overcome this problem. I've changed the function so it was caching its own result, and it was not trying to get the data over and over again before some definite time is passes. It was working very nice. But later on I've noticed several other functions those had to have this functionality.
So I've decided to use a decorator that decorates the functions with that ability. Here is the decorator:
####################################################################### class CachedMethod(object): """caches the result of a class method inside the instance """ #---------------------------------------------------------------------- def __init__(self, method): # record the unbound-method and the name #print "running __init__ in CachcedMethod" if not isinstance( method, property ): self._method = method self._name = method.__name__ self._isProperty = False else: self._method = method.fget self._name = method.fget.__name__ self._isProperty = True self._obj = None #---------------------------------------------------------------------- def __get__(self, inst, cls): """use __get__ to get the instance object and create the attributes if it is a property call __call__ """ #print "running __get__ in CachcedMethod" self._obj = inst if not hasattr( self._obj, self._name + "._data"): #print "creating the data" setattr ( self._obj, self._name + "._data", None ) setattr ( self._obj, self._name + "._lastQueryTime", 0 ) setattr ( self._obj, self._name + "._maxTimeDelta", 60 ) #print "finished creating data" if self._isProperty: return self.__call__() else: return self #---------------------------------------------------------------------- def __call__(self, *args, **kwargs): """ """ #print "running __call__ in CachedMethod" delta = time.time() - getattr( self._obj, self._name + "._lastQueryTime" ) if delta > getattr(self._obj, self._name + "._maxTimeDelta") or getattr(self._obj, self._name + "._data" ) == None: # call the function and store the result as a cache #print "caching the data" data = self._method(self._obj, *args, **kwargs ) setattr( self._obj, self._name + "._data", data ) # zero the time lastQueryTime = time.time() setattr( self._obj, self._name + "._lastQueryTime", time.time() ) #else: #print "returning the cached data" return getattr( self._obj, self._name + "._data" ) #---------------------------------------------------------------------- def __repr__(self): """Return the function's representation """ objectsRepr = str(self._obj) objectsName = objectsRepr.split(' ')[0].split('.')[-1] cachedObjectsRepr = '' return cachedObjectsRepr
You can use that anywhere you want, but beware that the caching is time dependent, not input dependent.
Comments