0

memoize関数をキャッシュできるデコレータを実装しました。キャッシュキーには関数の引数が含まれています。同様に、cachedデコレータは関数をキャッシュしますが、引数を無視します。コードは次のとおりです。

class ApplicationCache (Memcached):

make_key方法:UltraJSONは文字列をすばやく配信し、SHA512はそれを鮮明な16進ダイジェストにハッシュします。

    def make_key (self, *args, **kwargs):

        kwargs.update (dict (enumerate (args)))
        string = ujson.encode (sorted (kwargs.items ()))
        hashed = hashlib.sha512 (string)

        return hashed.hexdigest ()

memoizeデコレータ:Python 2.xは完全修飾関数名を吸うので、私は単にユーザーに妥当なものを提供するように強制しますname

    def memoize (self, name, timeout=None):
        assert name

        def decorator (fn):
            @functools.wraps (fn)
            def decorated (*args, **kwargs):

                key = self.make_key (name, *args, **kwargs)
                cached = self.get (key)

                if cached is None:
                    cached = fn (*args, **kwargs)
                    self.set (key, cached, timeout=timeout)

                return cached
            return decorated
        return decorator

cachedデコレータ:引数を無視するmemoize1つの例外を除いて、ほぼ逐語的なコピーです。make_key

    def cached (self, name, timeout=None):
        assert name

        def decorator (fn):
            @functools.wraps (fn)
            def decorated (*args, **kwargs):

                key = self.make_key (name) ## no args!
                cached = self.get (key)

                if cached is None:
                    cached = fn (*args, **kwargs)
                    self.set (key, cached, timeout=timeout)

                return cached
            return decorated
        return decorator

さて、私の問題cachedは、それがリファクタリングのために悲鳴を上げることです:それは使用する必要があり、アイデアは次のように(多分使用して?)memoizeの議論を排除することです:fnfunctools.partial

    def cached (self, name, timeout=None):

        ## Reuse the more general `memoize` to cache a function,
        ## but only based on its name (ignoring the arguments)

ここでDRYの原則をやり過ぎているかどうか、また再利用が可能かどうかは実際にはわかりません。現在の実装では、キーの作成中にのみcached引数が無視されるためです(ただし、装飾された関数の呼び出し中は明らかにそうではありません)

4

1 に答える 1

1

引数を取り除きname、キー関数を引数として提供します。

def memoize(self, timeout=None, keyfunc=self.make_key):
    ...
    key = keyfunc(function.__name__, *args, **kwargs)
    ...

cacheその後、次のようになります。

def cache(self, timeout=None):
    return self.memoize(timeout, keyfunc=lambda f, *args, **kwargs: f.__name__)
于 2012-12-30T14:46:18.360 に答える