Python functools.lru_cache的typed参数未按文档描述工作
关于functools.lru_cache中typed参数的误解澄清
你遇到的问题其实是测试例子没选对,误把lru_cache对特定类型的缓存键优化当成了typed参数的作用。先给你拆解清楚:
首先,官方文档里的typed=True,核心作用是当两个参数值相等(a == b为真)、哈希值也相同,但类型不同时,会被当成独立的调用分别缓存。而你的例子里,4(int)和4.0(float)虽然值相等、哈希相同,但因为lru_cache对部分类型有特殊优化,导致它们的缓存键生成逻辑不一样,和typed参数无关:
- int属于源码定义的
fasttypes集合(包含int, str, frozenset, type(None)),单个int参数会直接用参数值作为缓存键; - float不属于
fasttypes,单个float参数会被包装成_HashedSeq((4.0,))作为缓存键。
这两个键完全不同,所以不管typed设成True还是False,都会被当成不同的缓存条目。
正确展示typed参数差异的例子
要看到typed的实际作用,得找两个值相等、哈希相同、类型不同,且缓存键生成逻辑一致的参数,比如自定义类实例和int:
from functools import lru_cache class MyInt: def __init__(self, value): self.value = value def __eq__(self, other): # 让MyInt实例和int可以比较相等 if isinstance(other, int): return self.value == other return isinstance(other, MyInt) and self.value == other.value def __hash__(self): # 哈希值和对应int一致 return hash(self.value) # 测试typed=False的情况 @lru_cache(typed=False) def f1(x): print(f"f1被调用,参数:{x}") return x.value if isinstance(x, MyInt) else x print("=== typed=False ===") f1(5) # 首次调用,打印日志 f1(MyInt(5)) # 值相等、哈希相同,且typed=False,直接命中缓存,无日志输出 print(f1.cache_info()) # 输出 hits=1, misses=1 # 测试typed=True的情况 @lru_cache(typed=True) def f2(x): print(f"f2被调用,参数:{x}") return x.value if isinstance(x, MyInt) else x print("\n=== typed=True ===") f2(5) # 首次调用,打印日志 f2(MyInt(5)) # typed=True会区分参数类型,重新调用并打印日志 print(f2.cache_info()) # 输出 hits=0, misses=2
运行这段代码就能看到明显差异:
typed=False时,f1(5)和f1(MyInt(5))共享同一个缓存;typed=True时,两者会被当成完全不同的调用,各自生成缓存条目。
总结
你的测试例子里的现象是lru_cache对fasttypes的特殊优化导致的,和typed参数的核心功能无关。只有当参数满足「值相等、哈希相同、类型不同」且缓存键生成逻辑一致时,typed参数才会体现出差异。
内容的提问来源于stack exchange,提问作者aloysius72
相关产品推荐
相关产品推荐

