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模拟登录百度代码分享(获取百度贴吧等级)
Dec 27 Python
python使用socket连接远程服务器的方法
Apr 29 Python
python制作爬虫爬取京东商品评论教程
Dec 16 Python
Python查找最长不包含重复字符的子字符串算法示例
Feb 13 Python
Python3.5实现的三级菜单功能示例
Mar 25 Python
django的分页器Paginator 从django中导入类
Jul 25 Python
pytorch获取vgg16-feature层输出的例子
Aug 20 Python
Anaconda+Pycharm环境下的PyTorch配置方法
Mar 13 Python
Python连接Hadoop数据中遇到的各种坑(汇总)
Apr 14 Python
Iconfont(矢量图标)+iconmoon(图标svg互转)配合javascript实现社交分享系统
Apr 21 Python
python实现Oracle查询分组的方法示例
Apr 30 Python
Python实现byte转integer
Jun 03 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
php使用curl获取https请求的方法
2015/02/11 PHP
[原创]php获取数组中键值最大数组项的索引值
2015/03/17 PHP
中高级PHP程序员应该掌握哪些技术?
2016/09/23 PHP
常用简易JavaScript函数
2009/04/09 Javascript
JsRender实用入门教程
2014/10/31 Javascript
jQuery中:checkbox选择器用法实例
2015/01/03 Javascript
浅谈javascript中this在事件中的应用
2015/02/15 Javascript
JavaScript的代码编写格式规范指南
2015/12/07 Javascript
原生js编写基于面向对象的分页组件
2016/12/05 Javascript
谈谈JavaScript中浏览器兼容问题的写法小议
2016/12/17 Javascript
JavaScript实现简单评论功能
2017/08/17 Javascript
sublime text配置node.js调试(图文教程)
2017/11/23 Javascript
layui 表格的属性的显示转换方法
2018/08/14 Javascript
JS实现将对象转化为数组的方法分析
2019/01/21 Javascript
vue实现的下拉框功能示例
2019/01/29 Javascript
使用watch在微信小程序中实现全局状态共享
2019/06/03 Javascript
[07:20]2018DOTA2国际邀请赛寻真——逐梦Mineski
2018/08/10 DOTA
如何运行Python程序的方法
2013/04/21 Python
Python2.7简单连接与操作MySQL的方法
2016/04/27 Python
深入理解python中的闭包和装饰器
2016/06/12 Python
浅析python打包工具distutils、setuptools
2018/04/20 Python
python对视频画框标记后保存的方法
2018/12/07 Python
python psutil模块使用方法解析
2019/08/01 Python
python 字符串常用方法汇总详解
2019/09/16 Python
使用python实现希尔、计数、基数基础排序的代码
2019/12/25 Python
python利用JMeter测试Tornado的多线程
2020/01/12 Python
keras实现图像预处理并生成一个generator的案例
2020/06/17 Python
tensorflow下的图片标准化函数per_image_standardization用法
2020/06/30 Python
python分布式爬虫中消息队列知识点详解
2020/11/26 Python
美国饼干礼物和美食甜点购买网站:Cheryl’s
2020/05/28 全球购物
媒矿安全生产承诺书
2014/05/23 职场文书
2014年教师节国旗下讲话稿
2014/09/10 职场文书
2014年纳税评估工作总结
2014/12/23 职场文书
五一劳动节慰问信
2015/02/14 职场文书
酒店开业主持词
2015/07/02 职场文书
Java数据结构之堆(优先队列)
2022/05/20 Java/Android