为类添加lru_cache后,后续实例是否必然与缓存实例同ID?
类添加lru_cache后,相同参数的后续实例是否必然引用原缓存实例的相同ID?
我在研究类的缓存机制,想用它解决代码里的问题,于是写了个测试类:
from functools import lru_cache @lru_cache class Foo: def __init__(self, a: int): self.a = a self.b = sum(i**2 for i in range(self.a))
测试后发现,用相同参数创建实例时,初始化耗时为0:
import datetime as dt start_1 = dt.datetime.now() bar = Foo(10_000) elapsed_1 = (dt.datetime.now() - start_1) # 4008 ms start_2 = dt.datetime.now() baz = Foo(5_000) elapsed_2 = (dt.datetime.now() - start_2) # 3003 ms start_3 = dt.datetime.now() boo = Foo(15_000) elapsed_3 = (dt.datetime.now() - start_3) # 5002 ms start_4 = dt.datetime.now() bbb = Foo(10_000) elapsed_4 = (dt.datetime.now() - start_4) # 0 ms
并且此时没有创建新对象,只是引用了已有实例:
id(bar) == id(bbb) # True
如果移除@lru_cache,相同参数会生成不同对象,上述判断为False。想确认:给类添加缓存后,后续实例是否必然引用原缓存实例的相同ID?
回答
是的,在缓存未被清理、参数完全一致且缓存未被淘汰的前提下,后续调用返回的必然是同一个实例,ID也完全相同。
原因很简单:Python里类本身是可调用对象,调用类(比如Foo(10000))本质是触发实例创建流程。用@lru_cache装饰类,其实是把类的调用过程包裹进了缓存逻辑——当你用相同参数调用类时,lru_cache会直接返回之前缓存的结果,也就是第一次创建的那个实例对象,不会走新的实例化流程,所以两次拿到的是同一个对象,id()自然相等。
但要注意几个例外情况:
- 如果lru_cache设置了
maxsize,当缓存条目达到上限,旧的缓存可能被LRU算法淘汰。此时再用相同参数调用类,会重新创建实例,ID就会变化。 - 调用
Foo.cache_clear()手动清理缓存后,相同参数的调用会重新创建实例,ID改变。 - 类的初始化参数必须是可哈希的(比如int、str这类),否则lru_cache根本无法生效,也就不存在复用实例的情况。
内容的提问来源于stack exchange,提问作者NotAName
相关产品推荐
相关产品推荐

