You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为类添加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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 12:25:00