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
デコレータ:引数を無視するmemoize
1つの例外を除いて、ほぼ逐語的なコピーです。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
の議論を排除することです:fn
functools.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
引数が無視されるためです(ただし、装飾された関数の呼び出し中は明らかにそうではありません)。