对于项目,我想缓存一个方法计算的结果。 一些约束:
我到目前为止所得到的是:
def cached_method(fun):
"""A memoize decorator for class methods."""
@functools.wraps(fun)
def get(self, *args, **kwargs):
"""Return the value if cached.
Get it, cache it and return it if not.
"""
try:
self._cache[fun]
except AttributeError:
self._cache = {}
except KeyError:
pass
return self._cache.setdefault(fun, {}).setdefault((args, tuple(kwargs.items())), fun(self, *args, **kwargs))
return get
然而,出了点问题。事实上,使用一个最小的例子,例如:
class TestClass(object):
@cached_method
def method(self, p_arg):
print 'sentinel'
return p_arg
sut = TestClass()
sut.method(2)
sut.method(2)
你会看到方法被调用两次('sentinel'被打印两次)
通过PDB检查我无法看到问题是什么,因为第二次_cache
实际上包含了所有需要的内容。
修改
正如评论中指出的那样,问题在于setdefault
,无论密钥是否被找到,它都会调用默认传递的参数(第二个)。
要解决此问题,请将以上return
行替换为:
results = self.cache.setdefault(fun, {})
try:
ret = results[(args, tuple(kwargs.items()))]
except KeyError:
ret = results[(args, tuple(kwargs.items()))] = fun(self, *args, **kwargs)
return ret