改进@martijn-pieters 对我的一个用例的回答;在这里,我创建了一个包装器,它适用于任何可以传递 kwarg skip_cache 的函数,以指定是返回缓存值还是再次计算该值。
from functools import lru_cache, wraps
def skippable_lru_cache(maxsize: int = 128, typed: bool = False):
def wrapper_cache(func):
cached_func = lru_cache(maxsize=maxsize, typed=typed)(func)
@wraps(func)
def wrapped_func(*args, **kwargs):
if 'skip_cache' in kwargs and kwargs['skip_cache'] == True:
# call the function directly
return func(*args, **kwargs)
else:
# Remove skip_cache from kwargs so that its value doesn't affect stored results
try:
del kwargs['skip_cache']
except:
pass
# use the lru_cache-wrapped version
return cached_func(*args, **kwargs)
wrapped_func.cache_info = cached_func.cache_info
return wrapped_func
return wrapper_cache
@skippable_lru_cache(maxsize=128)
def calc(v1: int, v2: int, skip_cache: bool = False):
return v1 * v2
print('Run 1:')
for i in range(20):
print(calc(i, 10))
print(calc.cache_info())
print('Run 2:')
for i in range(20):
print(calc(i, 10, skip_cache=i > 9))
print(calc.cache_info())
结果:
Run 1:
0
10
20
30
40
50
60
70
80
90
100
110
120
130
140
150
160
170
180
190
CacheInfo(hits=0, misses=20, maxsize=128, currsize=20)
# All Run 1 calls are supposed to be hitting a miss as they are requesting cached value, but none are cached, generating a cache of size 20
Run 2:
0
10
20
30
40
50
60
70
80
90
100
110
120
130
140
150
160
170
180
190
CacheInfo(hits=10, misses=20, maxsize=128, currsize=20)
# For Run 2, only first 10 calls are requesting cache value, which shows in CacheInfo as hits=10 while still keeping the cache size at 20 although skip_cache is present with different value. For the second 10 calls, cache is completely being skipped resulting in the calls not registering as hit or miss, nor affecting the cache size