【发布时间】:2012-12-30 14:35:43
【问题描述】:
我已经实现了一个memoize 装饰器,它允许缓存一个函数。缓存键包括函数参数。类似地,cached 装饰器缓存了一个函数,但忽略了参数。代码如下:
class ApplicationCache (Memcached):
make_key 方法:UltraJSON 快速传递一个字符串,SHA512 散列成清晰的十六进制摘要:
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 糟透了 w.r.t。完全限定的函数名,我只是强制用户提供一个合理的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 的逐字复制,唯一的例外是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 的当前实现在构建密钥时忽略了参数 only (但显然 不是 在调用装饰函数时)。
【问题讨论】:
标签: python decorator partial code-reuse