pythonのデコレータを勉強するためにmemoizedにlruとtimeout機能を追加してみた

Pythonのデコレータって面白い。
メモ化(Memoization)も簡単に、そして美しく実現できる。

何かDBにアクセスして得られる結果をメモ化でキャッシュして、アプリケーションの動作を高速化したりできるだろう。

ただ無尽蔵に引数と結果の組み合わせをキャッシュされても困る。それにキャッシュするなら、期間も指定したい。

ということでちょっと書き換えてそれを実現してみた。

memoizationは以下のページのものを元とした。
https://wiki.python.org/moin/PythonDecoratorLibrary#Memoize

ソースコード
import pylru
import time

class memoized_lru(object):
    '''Decorator. Caches a function's return value each time it is called.                                                                                                                                           
    If called later with the same arguments, the cached value is returned                                                                                                                                            
    (not reevaluated).                                                                                                                                                                                               
    '''
    def __init__(self, func, cachesize=1024, expire=1):
        self.func = func
        self.cache = cache = pylru.lrucache(cachesize)
        self.expire = expire

    def __call__(self, *args):
        if not isinstance(args, collections.Hashable):
            # uncacheable. a list, for instance.                                                                                                                                                                     
            # better to not cache than blow up.                                                                                                                                                                      
            return self.func(*args)
        if args in self.cache:
            (value, ts) = self.cache[args]
            now_ts = time.time()
            if (now_ts - ts) < self.expire:
                return value
        # no valid cache! call function.                                                                                                                                                                             
        value = self.func(*args)
        ts = time.time()
        self.cache[args] = (value, ts)
        return value

    def __repr__(self):
            '''Return the function's docstring.'''
            return self.func.__doc__

    def __get__(self, obj, objtype):
        '''Support instance methods.'''
        return functools.partial(self.__call__, obj)