Python3之使用@property
在绑定属性时,如果我们直接把属性暴露出去,虽然写起来简单,但是,没有办法检查参数,导致可以把成绩随便改
1 2 3 4 5 6 7 8 9 10 | >>> class Student( object ): ... pass ... >>> s = Student() >>> s.score = 999 >>> s.score 999 >>> s.score = 'abc' >>> s.score 'abc' |
这显然不会逻辑,为了现在score的范围可以,通过一个set_score()方法,同通过一个get_score()来获取成绩,这样,在set_score()方法里,就可以检查参数:
1 2 3 4 5 6 7 8 9 | class Student( object ): def get_score( self ): return self ._score def set_score( self ,value): if not isinstance (value, int ): raise ValueError( 'score must be an integer!' ) if value< 0 or value > 100 : raise ValueError( 'score must between 0~100!' ) self ._score = value |
现在,对人员的Student实例进行操,就不能随心所欲地设置score了
1 2 3 4 5 6 7 8 | >>> s.set_score( 100 ) >>> s.get_score() 100 >>> s.set_score( 101 ) Traceback (most recent call last): File "<stdin>" , line 1 , in <module> File "<stdin>" , line 8 , in set_score ValueError: score must between 0 ~ 100 ! |
但是,上面的调用方法比较复杂,有没有直接用属性这么直接减掉
有没有既能检查参数,又可以有类似属性这样的简单方式来访问类的变量呢。对于类的方法,装饰器一样起作用。python内置的@property装饰器就是负责把一个方法变成属性调用的:
1 2 3 4 5 6 7 8 9 10 11 | class Student( object ): @property def score( self ): return self ._score @score .setter def score( self ,value): if not isinstance (value, int ): raise ValueError( 'score must be an integer!' ) if value< 0 or value > 100 : raise ValueError( 'score must between 0~100!' ) self ._score = value |
@property的实现比较复杂,这里看如何使用。把一个getter的方法变成属性,只需要加上@property就可以了,此时,@property本身又创建了另一个装饰器,负责把一个setter方法变成属性赋值,于是我们就拥有了一个可控的属性操作:
1 2 3 4 5 6 7 8 9 | >>> s = Student() >>> s.score = 100 >>> s.score 100 >>> s.score = 101 Traceback (most recent call last): File "<stdin>" , line 1 , in <module> File "<stdin>" , line 18 , in score ValueError: score must between 0 ~ 100 ! |
注意到这个神奇的@property,我们再对实例属性操作的时候,就知道该属性很可能不是直接暴露的,而是通过getter和setter方法来实现的。
还可以只定义只读属性,只定义getter方法,不定义setter方法就是一个只读属性
1 2 3 4 5 6 7 8 9 10 11 12 | class Student( object ): #出生年格式为2001 @property def birth( self ): return self ._birth @birth .setter def birth( self ,value): self ._birth = value #年龄age定义为只读即没有setter属性 @property def age( self ): return 2019 - self ._birth |
操作
1 2 3 4 5 6 7 8 9 10 | >>> s = Student() >>> s.birth = 2000 #age是根据birth用2019-birth计算出来的 >>> s.age 19 #直接修改age因为没有定义setter使用报错 >>> s.age = 20 Traceback (most recent call last): File "<stdin>" , line 1 , in <module> AttributeError: can't set attribute |
练习
利用@property给一个Screen对手加上width和heigth属性,已经一个只读属性resolution Screen.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | class Screen( object ): #设置长 @property def width( self ): return self ._width #检查输入是否规范必须是int并且大于0 @width .setter def width( self ,value): if not isinstance (value, int ): raise ValueError( 'width must be an integer!' ) if value < 0 : raise ValueError( 'width must > 0' ) self ._width = value #设置高 @property def height( self ): return self ._height @height .setter def height( self ,value): if not isinstance (value, int ): raise ValueError( 'height must be an integer!' ) if value < 0 : raise ValueError( 'height must > 0' ) self ._height = value #面积只设置getter方法通过长乘高得到 @property def resolution( self ): return self ._width * self ._height s = Screen() s.width = 1024 s.height = 768 print (s.resolution) |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
2017-06-28 ELKStack之使用Redis作为消息队列