class Cache ( object ): """ >>> dec_cache = Cache(10) >>> @dec_cache ... def identity(f): ... return f >>> dummy = [identity(x) for x in range(20) + range(11,15) + range(20) + ... range(11,40) + [39, 38, 37, 36, 35, 34, 33, 32, 16, 17, 11, 41]] >>> dec_cache.t1 deque([(41,)]) >>> dec_cache.t2 deque([(11,), (17,), (16,), (32,), (33,), (34,), (35,), (36,), (37,)]) >>> dec_cache.b1 deque([(31,), (30,)]) >>> dec_cache.b2 deque([(38,), (39,), (19,), (18,), (15,), (14,), (13,), (12,)]) >>> dec_cache.p 5 """ def __init__ ( self , size ): self . cached = {} self . c = size self . p = 0 self . t1 = deque () self . t2 = deque () self . b1 = deque () self . b2 = deque () def replace ( self , args ): if self . t1 and ( ( args in self . b2 and len ( self . t1 ) == self . p ) or ( len ( self . t1 ) > self . p )): old = self . t1 . pop () self . b1 . appendleft ( old ) else : old = self . t2 . pop () self . b2 . appendleft ( old ) del ( self . cached [ old ]) def __call__ ( self , func ): def wrapper ( * orig_args ): """decorator function wrapper""" args = orig_args [:] if args in self . t1 : self . t1 . remove ( args ) self . t2 . appendleft ( args ) return self . cached [ args ] if args in self . t2 : self . t2 . remove ( args ) self . t2 . appendleft ( args ) return self . cached [ args ] result = func ( * orig_args ) self . cached [ args ] = result if args in self . b1 : self . p = min ( self . c , self . p + max ( len ( self . b2 ) / len ( self . b1 ) , 1 )) self . replace ( args ) self . b1 . remove ( args ) self . t2 . appendleft ( args ) #print "%s:: t1:%s b1:%s t2:%s b2:%s p:%s" % ( # repr(func)[10:30], len(self.t1),len(self.b1),len(self.t2), # len(self.b2), self.p) return result if args in self . b2 : self . p = max ( 0 , self . p - max ( len ( self . b1 ) / len ( self . b2 ) , 1 )) self . replace ( args ) self . b2 . remove ( args ) self . t2 . appendleft ( args ) #print "%s:: t1:%s b1:%s t2:%s b2:%s p:%s" % ( # repr(func)[10:30], len(self.t1),len(self.b1),len(self.t2), # len(self.b2), self.p) return result if len ( self . t1 ) + len ( self . b1 ) == self . c : if len ( self . t1 ) < self . c : self . b1 . pop () self . replace ( args ) else : del ( self . cached [ self . t1 . pop ()]) else : total = len ( self . t1 ) + len ( self . b1 ) + len ( self . t2 ) + len ( self . b2 ) if total >= self . c : if total == ( 2 * self . c ): self . b2 . pop () self . replace ( args ) self . t1 . appendleft ( args ) return result return wrapper