functools.cached_property 仅适用于带 self 的实例方法,因其底层依赖描述符协议和实例 __dict__ 缓存:首次调用将结果写入 instance.__dict__,后续直接读取;若缺失 self、用于 @staticmethod/@classmethod 或在类体中直接赋值,则因无法绑定实例而抛出 TypeError。

functools.cached_property 在 Python 3.8 中可用,但仅限于 CPython 实现,且必须确保装饰的是实例方法(非静态/类方法),否则会报 TypeError: cached_property() only works on methods。
为什么不能直接用在普通属性或函数上?
cached_property 的底层依赖描述符协议和实例字典缓存,它会在第一次调用时把结果写入 instance.__dict__,后续直接取值。如果目标不是绑定方法(比如写了 @cached_property 却没带 self 参数),解释器无法获取所属实例,就会失败。
常见错误现象:
- 定义成
def my_prop():(缺self)→ 报错TypeError - 误用于
@staticmethod或@classmethod→ 同样触发TypeError - 在类体中直接赋值(如
val = cached_property(...))→ 不生效,因为没走描述符访问流程
怎么正确声明并使用?
必须是带 self 的实例方法,返回值会被缓存到实例字典中。一旦计算过,后续访问不触发重新计算,也不走 __get__ 描述符逻辑。
实操建议:
- 方法名应语义清晰,体现“属性”而非“动作”,例如
full_name、config_dict,避免get_full_name() - 内部可安全调用其他实例属性或方法,只要它们本身不依赖未初始化的
cached_property - 若属性依赖外部状态(如文件内容、网络响应),需自行处理失效逻辑——
cached_property不提供刷新机制
示例:
from functools import cached_property
<p>class DataProcessor:
def <strong>init</strong>(self, path):
self.path = path</p><pre class="brush:php;toolbar:false;">@cached_property
def raw_content(self):
print("Reading file...") # 仅首次执行
with open(self.path) as f:
return f.read()
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
和手动实现的惰性属性比,有什么代价?
优势是简洁、线程安全(CPython 中对单个实例的 __dict__ 写入是原子的)、符合 Python 惯例;劣势是内存占用不可控——每个实例都会保留一份缓存值,且无法主动清除(除非手动删 obj.__dict__['attr_name'])。
需要注意的点:
- 不支持
del obj.attr删除缓存(会报AttributeError),必须用del obj.__dict__['attr'] - 继承时子类重写同名方法不会自动覆盖父类的
cached_property,因为描述符查找优先级高,但若子类也加了@cached_property,则会覆盖——此时要注意初始化顺序 - 在
__slots__类中可用,但要求__dict__仍存在(即不能把'__dict__'排除在__slots__外)
替代方案:什么时候不该用 cached_property?
当需要控制缓存生命周期、按条件刷新、或结果体积极大且多数实例从不访问该属性时,cached_property 就不合适。
更灵活的做法:
- 用普通方法 + 显式缓存字典(如
self._cache = {}),自己管理键和失效 - 用
property+getattr/setattr手动检查缓存,适合需要延迟初始化但又不想固定绑定到__dict__的场景 - 第三方库如
lazy-object-proxy或自定义描述符,支持__delete__和更细粒度控制
真正关键的不是“能不能缓存”,而是“缓存是否应该随实例生命周期一直存在”。这点容易被忽略,尤其在长时运行的服务中——一个被遗忘的 cached_property 可能悄悄拖慢 GC 或撑爆内存。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










