0. 一句话定位
| 维度 | 内容 |
|---|---|
| 作用对象 | 类实例方法 |
| 使用场景 | 属性访问 |
| 来源 | 标准库 builtins.property |
| 语法形式 | @property;可选 @name.setter / @name.deleter |
段末注释:描述符(descriptor) 协议中,
property把方法包装成obj.attr形式的访问接口。
1. 做什么
将 obj.method() 变为 obj.method 的属性访问;可在 setter 中校验或转换,用 _field 存真实数据,对外隐藏内部字段名。
2. 重点参数
| 参数 | 类型 | 默认值 | 作用 | 配置建议 |
|---|---|---|---|---|
fget |
callable | — | 读取时调用 | 通常 @property 装饰方法,不显式传 |
fset |
callable | None |
写入时调用 | @x.setter 定义;不设则只读 |
fdel |
callable | None |
del obj.x 时调用 |
少见;需 @x.deleter |
doc |
str | None |
属性文档 | 默认继承 fget 的 __doc__ |
3. 最小可运行示例
1 | class DataSet: |
带 setter 的完整示例:
1 | class DataSet: |
4. 常见变体
- 只读属性:仅
@property,不定义 setter - 计算属性:getter 内按需计算,不缓存(需缓存见
functools.cached_property) - 与 deleter:
@images.deleter配合del obj.images
5. 适用 / 不适用
适用
- 对外暴露字段,但需在读取/写入时做校验或惰性计算
- 希望 API 用
obj.name而非obj.get_name()
不适用
- 简单数据容器且无校验需求(直接用
__init__赋值即可) - 需要
@classmethod/@staticmethod语义的方法(不能直接与@property叠在同一方法上)
6. 易踩坑
- 只写
@property无 setter 时赋值会AttributeError: can't set attribute - setter 内写
self.images = value会无限递归,应写self._images = value @property与@classmethod不能叠在同一 def 上;类级「属性」用描述符或元类
7. 近邻替代
| 替代 | 何时用 |
|---|---|
functools.cached_property |
首次访问后缓存结果,适合昂贵计算 |
普通方法 get_x() |
不需要属性语法、无 setter 需求 |