【发布时间】:2022-05-23 14:36:28
【问题描述】:
我正在经历 Python 的 LRU 缓存装饰器的实现 details。为了正确理解 lru_cache 装饰器在不同场景中的行为,我还阅读了以下 SO 答案:
- Python LRU Cache Decorator Per Instance
- Python: building an LRU cache
- Python LRU cache in a class disregards maxsize limit when decorated with a staticmethod or classmethod decorator
到目前为止,我可以看出这三种情况下的缓存行为是不同的:
- 在全局命名空间中装饰一个函数。
- 装饰类中的实例方法。
- 装饰类中的方法,该方法稍后会使用
staticmethod或classmethod装饰器进行装饰。
第一种情况是幸福的路径,每个用lru_cache 装饰器装饰的函数都有自己的缓存。这已经很好了documented。在第二种情况下,缓存在类的多个实例之间共享,其中每个实例对于实例方法的相同参数将具有不同的键。这在我列出的最后一个问题中得到了很好的解释。在第三种情况下,缓存也在封装类的多个实例之间共享。但是,由于静态方法或类方法不将self 作为其第一个参数,因此类的实例不会为相同的参数创建单独的缓存条目。
我的问题是——什么实现细节定义了这种行为?在lru_cache函数的实现中,我只能看到_lru_cache_wrapper函数内部的一个本地缓存字典正在保存缓存条目。这是sn-p:
def _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo):
sentinel = object()
make_key = _make_key
PREV, NEXT, KEY, RESULT = 0, 1, 2, 3
cache = {} # This is a local dict,
# then how come the instance cache entries are shared?
我不明白的是,当 lru_cache 装饰器应用于驻留在类中的方法时,该本地缓存字典如何在类的实例之间共享?我希望它的行为与第一种情况相同,即每个实体都有自己的缓存并且没有共享任何内容。
【问题讨论】:
标签: python python-3.x caching lru