我了解cache_clear
。但是,我想知道如何清除单个呼叫的缓存。看到cache_clear
不接受参数,我认为唯一的方法是直接弄乱基础字典。会有什么副作用(如果有)?
目标是实现以下目标
from functools import lru_cache
@lru_cache()
def f(x):
print('called with ', x)
f(1)
f.cache_clear(1) # obviously does not work
f(1)
带有输出
called with 1
called with 1
答案 0 :(得分:1)
这应该被认为是不可能的。没有公用的API,根本没有访问缓存的属性,也没有统一的缓存键格式。即使您采取了严厉的措施(gc
/ ctypes
来获取高速缓存,您也可能会破坏整个LRU系统,到处泄漏大量内存,甚至可能出现段错误。 implementation中的内存管理在面对直接破坏缓存的人时并不安全。
答案 1 :(得分:0)
我成功地为 Python redis 支持的 lru 缓存装饰器实现了一个细粒度的 cache_clear()
- 参见 gist。这是 lru_cache
的一种与 Python 3 附带的完全不同的实现,我可以理解它的内部结构并进行必要的更改。
特别是,cache_clear()
得到了增强,因此如果您传递参数,缓存将被部分清除 - 仅针对该特定调用签名。这确实允许更精细的缓存清除。
在此过程中,我学到了一些很深的东西,这为这次讨论提供了一些启示,这可能是 Python 3 没有采用细粒度缓存清除的一个原因。
我发现这种增强的 cache_clear()
行为需要非常小心使用,因为同时
例如f(1)
和 f(param=1)
意思相同,lru 缓存系统会缓存那些
两个调用作为单独的条目。然后当你使一种调用方式无效时
f.cache_clear(1)
这使得另一种调用方式 f(param=1)
仍然被缓存并且
返回陈旧的值 - 即使在语义上这两种调用风格是
相同的。因此,如果您确实精细地使用 cache_clear,请确保重复调用它
您可能使用过的所有可能的参数签名,例如f.cache_clear(1)
;
f.cache_clear(param=1)
。
我想可能有一种算法可以计算出等效的参数 (*args, **kwargs)
的所有可能排列?那么这种细粒度的缓存清除方法使用起来会安全得多。