Python类实例方法memoization能否使用functools.cache?性能如何?
问题解答
1. @functools.cache 用于实例方法的影响
确实会因为入参包含self产生问题,不止是性能,还有更严重的内存泄漏风险:
- 性能层面:
@cache默认会把所有入参(包括self实例本身)作为缓存键的组成部分,实例数量多的时候,缓存条目会成倍膨胀:比如你创建1000个Test实例,每个都调用一次test(1,2),缓存里会存储1000条独立的条目,而不是复用1条。条目越多哈希冲突概率越高,查找开销也会随之上升。 - 内存泄漏层面:
@cache的缓存是挂载在函数对象上的全局缓存,会持有self的强引用,哪怕你外部把实例销毁了,缓存里的引用还在,实例永远不会被垃圾回收,内存占用会只增不降。
2. 手写实例缓存和@cache的性能对比
两者的功能逻辑本身就不一样,性能表现分场景:
- 如果你的实例数量很少:
@cache因为底层是CPython的C实现,单次命中的查找开销会比你手写的Python层字典操作略快一点。 - 如果实例数量多、调用参数组合多:
@cache的缓存条目会快速膨胀,这时候你手写的每个实例独立维护小缓存的方案,查找效率反而更高,而且不会有内存泄漏的问题,实例销毁时缓存也会跟着释放。 - 额外的灵活性优势:手写缓存你可以自由加淘汰逻辑,比如限制缓存大小、定期清理过期条目,
@cache默认无上限,除非你手动设置maxsize,但还是解决不了self导致的缓存冗余和内存泄漏问题。
如果你不想手写缓存,又要给实例方法加缓存,可以用functools.cached_property(针对无入参的属性方法),或者第三方库提供的@cachedmethod类方法专用缓存装饰器,本质就是帮你封装了和你手写逻辑一致的、把缓存存在实例身上的实现。
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

