一、先搞懂:我们为什么要用 @property?
1. 原始问题
直接给对象赋值,没法检查数据是否合法:
class Student: pass s = Student() s.score = 9999 # 成绩不可能是9999,完全不合理!2. 笨办法解决(太麻烦)
写get_xxx和set_xxx方法手动检查:
class Student: def get_score(self): return self._score def set_score(self, value): # 检查:必须是整数、0-100之间 if not isinstance(value, int): raise ValueError("必须是整数") if value < 0 or value > 100: raise ValueError("成绩必须0~100") self._score = value调用时要写方法,一点都不简洁:
s = Student() s.set_score(60) print(s.get_score())3. 终极方案:@property
✅ 既能检查数据✅ 又能()
二、核心知识点:@property 怎么用?
1. 两个关键装饰器
- @property:把一个方法变成可读属性(getter)
- @方法名.setter:把一个方法变成可写属性(setter,用来检查数据)
2. 固定写法(万能模板)
class 类名: @property def 属性名(self): return self._属性名 # 前面加下划线,避免重名递归! @属性名.setter def 属性名(self, 值): # 这里写数据检查 self._属性名 = 值3. 重要警告(必看!)
属性方法名 ≠ 实例变量名
错误写法会无限递归、程序崩溃:
# ❌ 错误! @property def birth(self): return self.birth # 无限调用自己正确写法:实例变量前面加下划线_
# ✅ 正确 @property def birth(self): return self._birth三、超简单实例(一看就懂)
实例 1:可读写 + 数据检查(成绩)
class Student: # 读:获取成绩 @property def score(self): return self._score # 写:设置成绩 + 检查 @score.setter # @方法名.setter**:把一个方法变成**可写属性**(setter,用来检查数据) def score(self, value): if not isinstance(value, int): # 判断数据类型 raise ValueError("成绩必须是整数!") if value < 0 or value > 100: raise ValueError("成绩必须 0~100!") self._score = value使用效果:
s = Student() s.score = 88 # 像属性一样赋值 print(s.score) # 像属性一样读取 s.score = 9999 # 报错!自动检查,保护数据实例 2:只读属性(不能修改)
只加@property,不加 setter就是只读:
class Student: @property def birth(self): return self._birth @birth.setter def birth(self, value): self._birth = value # 只读属性:只能看,不能改 @property def age(self): return 2025 - self._birth使用效果:
s = Student() s.birth = 2000 print(s.age) # 25,可以读 s.age = 18 # 报错!不能修改四、思路总结(做题万能思路)
- 要给类加可控属性,就用
@property - 读方法:
@property+ 返回self._变量 - 写方法:
@变量.setter+ 数据检查 + 赋值self._变量 - 只读属性:只写
@property,不写 setter - 变量名前必须加
_,防止递归崩溃
五、课后练习题(教程原题 + 完整答案)
题目要求
给Screen类加上:
width:可读写,普通属性height:可读写,普通属性resolution:只读属性= width × height
## 五、课后练习题(教程原题 + 完整答案) ### 题目要求 # 给 `Screen` 类加上: # 1. `width`:可读写,普通属性 # 2. `height`:可读写,普通属性 # 3. `resolution`:**只读属性** = width × height class Screen: ##属性1 @property def width(self):#可读 return self._width @width.setter #可写 def width(self,value): self._width=value ##属性2 @property def height(self):#可读 return self._height @height.setter #可写 def height(self,value): self._height=value ##属性3 只读 @property def resolution(self): return self._width*self._height完整答案(直接复制运行)
class Screen(object): # width 可读写 @property def width(self): return self._width @width.setter def width(self, value): self._width = value # height 可读写 @property def height(self): return self._height @height.setter def height(self, value): self._height = value # resolution 只读属性 = 宽 × 高 @property def resolution(self): return self._width * self._height # 测试代码 s = Screen() s.width = 1024 s.height = 768 print('resolution =', s.resolution) if s.resolution == 786432: print('测试通过!') else: print('测试失败!')运行结果
resolution = 786432 测试通过!六、必背总结
- @property = 让方法像属性一样读
- @xxx.setter = 让方法像属性一样写 + 检查数据
- 实例变量必须用
_变量名,避免死循环 - 只写
@property就是只读属性 - 好处:代码简单 + 数据安全
=分割线=理解@property
@property 作用:告诉 Python这个 def 里面写的取数据流程,不要当成函数调用直接当成普通属性来用