Python进阶之@property动态属性的实现


Posted in Python onApril 01, 2019

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 优化了属性读取和设置的可读性
  • 需要限制属性的特征;
  • 只读属性。如果属性只可以读,不可以写,用起来很方便。
  • 这个属性根据一个变化的环境动态改变。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
解决python写的windows服务不能启动的问题
Apr 15 Python
python中map、any、all函数用法分析
Apr 21 Python
Python中输出ASCII大文字、艺术字、字符字小技巧
Apr 28 Python
几个适合python初学者的简单小程序,看完受益匪浅!(推荐)
Apr 16 Python
Django中使用极验Geetest滑动验证码过程解析
Jul 31 Python
python文件处理fileinput使用方法详解
Jan 02 Python
Python爬虫库BeautifulSoup的介绍与简单使用实例
Jan 25 Python
python实现FTP循环上传文件
Mar 20 Python
解决jupyter notebook显示不全出现框框或者乱码问题
Apr 09 Python
python中urllib.request和requests的使用及区别详解
May 05 Python
Python爬虫爬取百度搜索内容代码实例
Jun 05 Python
Java Unsafe类实现原理及测试代码
Sep 15 Python
彻底理解Python中的yield关键字
Apr 01 #Python
python抓取搜狗微信公众号文章
Apr 01 #Python
Python使用os.listdir()和os.walk()获取文件路径与文件下所有目录的方法
Apr 01 #Python
python装饰器简介---这一篇也许就够了(推荐)
Apr 01 #Python
Python批量删除只保留最近几天table的代码实例
Apr 01 #Python
Python中的Socket 与 ScoketServer 通信及遇到问题解决方法
Apr 01 #Python
python assert的用处示例详解
Apr 01 #Python
You might like
从康盛产品(discuz)提取出来的模板类
2011/06/28 PHP
10个简化PHP开发的工具
2014/12/25 PHP
php中foreach结合curl实现多线程的方法分析
2016/09/22 PHP
jQuery 1.5 源码解读 面向中高阶JSER
2011/04/05 Javascript
javascript右下角弹层及自动隐藏(自己编写)
2013/11/20 Javascript
js实现按一下删除键删除整个单词附demo
2014/09/05 Javascript
jQuery实现多按钮单击变色
2014/11/27 Javascript
详解JavaScript的while循环的使用
2015/06/03 Javascript
AngularJS 所有版本下载地址
2016/09/14 Javascript
JavaScript自定义函数实现查找两个字符串最长公共子串的方法
2016/11/24 Javascript
用原生js做单页应用
2017/01/17 Javascript
支持移动端原生js轮播图
2017/02/16 Javascript
js轮播图透明度切换(带上下页和底部圆点切换)
2017/04/27 Javascript
详解Vue使用命令行搭建单页面应用
2017/05/24 Javascript
Vue.js中兄弟组件之间互相传值实例
2017/06/01 Javascript
原生JS+Canvas实现五子棋游戏实例
2017/06/19 Javascript
nodejs连接mysql数据库及基本知识点详解
2018/03/20 NodeJs
[04:44]DOTA2 2017全国高校联赛视频回顾
2017/08/21 DOTA
在Django中管理Users和Permissions以及Groups的方法
2015/07/23 Python
python实现kNN算法
2017/12/20 Python
Python编程实现的简单神经网络算法示例
2018/01/26 Python
python如何对实例属性进行类型检查
2018/03/20 Python
python 统计数组中元素出现次数并进行排序的实例
2018/07/02 Python
使用Python实现在Windows下安装Django
2018/10/17 Python
Python用5行代码写一个自定义简单二维码
2018/10/21 Python
钉钉群自定义机器人消息Python封装的实例
2019/02/20 Python
python2 中 unicode 和 str 之间的转换及与python3 str 的区别
2019/07/25 Python
canvas实现滑动验证的实现示例
2020/08/11 HTML / CSS
美国机场停车位预订:About Airport Parking
2018/03/26 全球购物
波兰灯具、照明和LED购物网站:Lampy.pl
2019/03/11 全球购物
餐厅楼面主管岗位职责范本
2014/02/16 职场文书
2015年毕业生自我鉴定模板
2014/09/19 职场文书
班子个人四风问题整改措施
2014/10/04 职场文书
2019幼儿园感恩节活动策划书
2019/11/28 职场文书
Spring Data JPA的Audit功能审计数据库的变更
2021/06/26 Java/Android
Java使用httpRequest+Jsoup爬取红蓝球号码
2021/07/02 Java/Android