Python 动态属性的概念可能会被面试问到,在项目当中也非常实用,但是在一般的编程教程中不会提到,可以进修一下。
先看一个简单的例子。创建一个 Student 类,我希望通过实例来获取每个学生的一些情况,包括名字,成绩等。成绩只有等到考试结束以后才会有,所以实例化的时候不会给它赋值。
class Student: def __init__(self, name): self.name = name self.score = None mike = Student('mike')
考试完以后,准备给 mike 打分:
mike.score = 999
在这里,老师一不小心多打了个 9 ,通常来说打分都是 100 分值,999 是一个非法数据,不应该赋值成功。学生一多,老师打分出现手误的情况肯定会越来越多,所以我们必须想办法修改程序,限制 score 的值必须在 0-100 分。
限制值
我们定义一个方法,如果输入的不是 0-100 的整数,就让程序报错,数据合法,我们就把 score 属性修改成功。
def set_score(self, new_score): if not isinstance(new_score, int): raise ValueError('score must be int') if 0 <= new_score <= 100: self.score = new_score return self.score else: raise ValueError('score invalid')
这样我们每次需要获取成绩的时候使用 self.score 获取,修改成绩的时候调用函数来修改:
mike.set_score(999)
调用以后会报错,因为 999 是非法数据。注意,这个时候我使用 self.score 还是可以进行设置,而且不报错:
self.score = 999
这显然是不行的。所以我们要提供一种机制,把 score 变成私有属性,不能让外部访问。很遗憾,python 的私有属性是伪私有。通常我们把 _ 开头的属性叫私有属性,但是这只是一种协议和规定,你看到下划线开头的属性,不要去访问了。你硬要访问,是可以的,python 并不会禁止。
使用 @property 的方式代替。
上面的方法虽然实现了功能,但是改变了属性的使用方式。平常是这样使用的:
# 获取属性 a = mike.score # 设置属性 mike.score = 99 @property def score(self): return self._score @score.setter def score(self, new_score): if not isinstance(new_score, int): raise ValueError('score must be int') if 0 <= new_score <= 100: self._score = new_score return self._score else: raise ValueError('score invalid')
动态属性的好处
- 统一了调用方式。self.score = 99 的方式,而不是函数调用的方式。
- _score 我们就不直接去使用了。你要用也可以,不建议。
- 如果我们一个属性只可以读,把 setter 部分注释掉就可以了。
现在我们来完善这个类,添加 birth 属性和年龄属性:
from datetime import datetime class Student: def __init__(self, name, birth=1920): self.name = name self._score = None self.birth = birth self.age = datetime.now().year - self.birth mike = Student('mike') print(mike.birth) print(mike.age)
birth 和 age 这两个是可以根据一个求出另外一个的。存在数据冗余问题。
age 属性这样是有问题的。mike 初始化的时候,age 已经被求出来了,如果我在下一年再去访问 age 属性,那他就是个错误的值。可以通过把 age 设成现在的秒数来验证:
self.age = datetime.now().second mike = Student('mike') time.sleep(5) print(mike.age) print(datetime.now().second)
动态显示
@property def age(self): return datetime.now().year - self.birth
注意,这里不要去设置 @age.setter ,因为他是动态变化的,你修改了会造成数据不一致,它只能作为一个只读属性。
@property 作用和应用场景:
- @property 优化了属性读取和设置的可读性
- 需要限制属性的特征;
- 只读属性。如果属性只可以读,不可以写,用起来很方便。
- 这个属性根据一个变化的环境动态改变。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
更新日志
- 雨林唱片《赏》新曲+精选集SACD版[ISO][2.3G]
- 罗大佑与OK男女合唱团.1995-再会吧!素兰【音乐工厂】【WAV+CUE】
- 草蜢.1993-宝贝对不起(国)【宝丽金】【WAV+CUE】
- 杨培安.2009-抒·情(EP)【擎天娱乐】【WAV+CUE】
- 周慧敏《EndlessDream》[WAV+CUE]
- 彭芳《纯色角3》2007[WAV+CUE]
- 江志丰2008-今生为你[豪记][WAV+CUE]
- 罗大佑1994《恋曲2000》音乐工厂[WAV+CUE][1G]
- 群星《一首歌一个故事》赵英俊某些作品重唱企划[FLAC分轨][1G]
- 群星《网易云英文歌曲播放量TOP100》[MP3][1G]
- 方大同.2024-梦想家TheDreamer【赋音乐】【FLAC分轨】
- 李慧珍.2007-爱死了【华谊兄弟】【WAV+CUE】
- 王大文.2019-国际太空站【环球】【FLAC分轨】
- 群星《2022超好听的十倍音质网络歌曲(163)》U盘音乐[WAV分轨][1.1G]
- 童丽《啼笑姻缘》头版限量编号24K金碟[低速原抓WAV+CUE][1.1G]