功能说明
LRUCache 用 OrderedDict 保存键值,读取命中时把键移到末尾,写入后如果超过容量就淘汰最前面的条目。所有操作由 RLock 保护,适合多线程共享。memoize 装饰器把单参数函数包成缓存查询:先查缓存,未命中再计算并写回,同时保留原函数元数据。
关键代码
def get(self, key: K) -> V | None:
with self._lock:
if key not in self._items:
self.misses += 1
return None
self.hits += 1
self._items.move_to_end(key)
return self._items[key]
move_to_end 是 O(1) 操作,这是选择 OrderedDict 而不是普通字典加列表的原因。
使用注意
- 缓存值为
None时会被当成未命中,memoize不适合返回None的函数;可改用哨兵对象区分。 - 只支持可哈希的键,示例装饰器限制为单参数,多参数需要把参数元组作为键。
- 没有过期时间,数据永久有效;需要 TTL 时应记录写入时间并在读取时检查。
stats()的命中率是累计值,不会自动重置。- 缓存不保证并发计算的去重,两个线程可能同时未命中并重复计算。
验证方式
示例容量为 2:连续访问 4 两次只计算一次,再访问 5、6 会把 4 淘汰,最后再访问 4 会重新计算。输出中的 calls 应为 4,stats 显示大小、命中、未命中和命中率。