有很多记忆化装饰器,但我很好奇如何编写一个支持任意函数签名的记忆化装饰器,但让函数决定何时记忆结果?像这样的东西:
def conditional_memoize(f):
cache = {}
@wraps(f)
def conditional_f(*args, **kwargs):
return f(*args, **kwargs)
return conditional_f
@conditional_memoize
def my_func(a, b, c):
if str(a) + str(b) + str(c) in cache:
return cache[str(a) + str(b) + str(c)]
res = # compute the result
if some_arbitrary_condition:
cache[str(a) + str(b) + str(c)] = res
return res
但是,我知道这行不通,因为
NameError
。无论如何,有一个聪明的方法来解决这个问题吗?我总是可以使用类方法和类缓存,只是想看看是否有一个装饰器模式。
让函数返回其所需的结果和指示是否应缓存结果的标志,或者让包装器将缓存对象传递给函数。 (或两者兼而有之!)无论哪种方式都可以,但我更喜欢第一种方法。也许是这样的......
import functools
def conditional_memoize(fn):
cache = {}
@functools.wraps(fn)
def wrapper(*args, **kwargs):
key = args + tuple(sorted(kwargs.iteritems()))
if key in cache:
return cache[key]
result, flag = fn(*args, **kwargs)
if flag:
cache[key] = result
return result
return wrapper
有一个名为 conditional-cache 的库提供了此功能。 有两种方法可以根据您的用例调整缓存。最常见的一种是根据输出进行缓存。例如:
from conditional_cache import lru_cache
# For example, if your condition is that the result is even
some_arbitrary_condition = lambda func_result: func_result % 2 = 0
@lru_cache(condition=some_arbitrary_condition)
def my_func(a, b, c):
res = # compute the result
return res
这样,只有当
condition
函数求值 True
时,结果才会被缓存。
或者,如果您的条件仅取决于输入,您可以做的是在调用后删除该元素缓存。例如:
from conditional_cache import lru_cache
some_arbitrary_condition = lambda a, b, c: (a + b - c) == 0
@lru_cache
def my_func(a, b, c):
res = # compute the result
return res
if some_arbitrary_condition(a, b, c):
my_func.cache_remove(a=a, b=b, c=c)
安装:
pip install conditional-cache