Python @property 装饰器教程
为什么需要属性装饰器
在面向对象编程中,直接暴露类的内部属性虽然能快速上手,但会完全失去对属性赋值与访问的控制权:比如分数可以设成负数、超高分,或者日期设成未来的格式,这些非法状态都会让程序变得不可靠。
为了填补这个漏洞,传统做法是使用 Java/C++ 风格的 getter/setter 方法:
但这样的调用太啰嗦了——明明是像“属性”一样的东西,却要写括号调用方法。Python 作为追求可读性与优雅性的语言,提供了更贴合习惯的方案:@property 装饰器。
@property 的基本用法
@property 的核心作用是把一个方法伪装成“属性”,同时保留封装的所有优势。
核心结构
完整示例(对应上面的 Student 类)
日常调用
完全和操作普通属性一样!
只读属性
如果只加 @property,不加对应的 @属性名.setter,这个属性就会变成只读属性——只能获取,不能修改,非常适合用来做「计算属性」(比如根据生日算年龄、根据宽高算分辨率)。
示例:带计算属性的 Student 类
测试只读属性
几个容易踩的坑
1. 属性名与内部变量名冲突 → 无限递归
如果把 @property 装饰的方法名和内部存储变量名完全一样,访问时会陷入“调用方法 → 访问同名变量 → 再次调用方法”的死循环。
正确做法:用单下划线前缀命名内部存储变量(Python 约定俗成的“内部私有属性”标识,不是强制语法,但外部直接访问会显得不专业)。
2. 忘记初始化内部变量 → AttributeError
如果不在 __init__ 或其他前置方法中初始化带单下划线的内部变量,第一次访问属性时会报错找不到变量。
实际应用示例:屏幕分辨率类
结合只读计算属性和合法值验证,写一个实用的 Screen 类:
测试这个类
最佳实践总结
- 什么时候用 @property?
- 需要对属性赋值做验证/转换(比如年龄必须≥0,名字必须是字符串)
- 需要创建只读的计算属性(比如根据宽高算面积)
- 需要向后兼容:原本是直接暴露属性,后来想加封装,用 @property 可以不用改外部调用代码
- 什么时候别用?
- 只是简单的赋值/获取,没有额外逻辑——直接暴露属性就行(Python 强调“我们都是成年人了,不乱改内部属性”)
- 命名规范要遵守
- 内部存储变量用单下划线前缀(
_score) - 暴露的属性名直接用直观的名称(
score)
- 内部存储变量用单下划线前缀(
最后
@property 装饰器完美平衡了面向对象的封装性和Python 的简洁性,既能保护类的内部状态,又不会让调用代码变得繁琐。掌握它,是写出优雅 Python 类接口的第一步~

