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 相关文章推荐
Flask框架中密码的加盐哈希加密和验证功能的用法详解
Jun 07 Python
Django卸载之后重新安装的方法
Mar 15 Python
Python针对给定列表中元素进行翻转操作的方法分析
Apr 27 Python
python3.6的venv模块使用详解
Aug 01 Python
Python闭包思想与用法浅析
Dec 27 Python
Python基础之条件控制操作示例【if语句】
Mar 23 Python
Python3.5局部变量与全局变量作用域实例分析
Apr 30 Python
TensorFlow dataset.shuffle、batch、repeat的使用详解
Jan 21 Python
基于Python组装jmx并调用JMeter实现压力测试
Nov 03 Python
Python爬取你好李焕英豆瓣短评生成词云的示例代码
Feb 24 Python
Python 解决空列表.append() 输出为None的问题
May 23 Python
使用Pytorch实现two-head(多输出)模型的操作
May 28 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
模拟flock实现文件锁定
2007/02/14 PHP
PHP中开发XML应用程序之基础篇 添加节点 删除节点 查询节点 查询节
2010/07/09 PHP
php安全之直接用$获取值而不$_GET 字符转义
2012/06/03 PHP
php中3种方法统计字符串中每种字符的个数并排序
2012/08/27 PHP
PHP jQuery表单,带验证具体实现方法
2014/02/15 PHP
PHP代码实现爬虫记录――超管用
2015/07/31 PHP
学习php设计模式 php实现门面模式(Facade)
2015/12/07 PHP
关于laravel 数据库迁移中integer类型是无法指定长度的问题
2019/10/09 PHP
javascript 学习之旅 (3)
2009/02/05 Javascript
使用原生js写的一个简单slider
2014/04/29 Javascript
iframe里的页面禁止右键事件的方法
2014/06/10 Javascript
JavaScript学习笔记之JS对象
2015/01/22 Javascript
js获取数组的最后一个元素
2015/04/14 Javascript
JS实现光滑展开合拢的菜单效果代码
2015/09/16 Javascript
全面解析JS字符串和正则表达式中的match、replace、exec等函数
2016/07/01 Javascript
Nodejs进阶:如何将图片转成datauri嵌入到网页中去实例
2016/11/21 NodeJs
jquery ajaxfileuplod 上传文件 essyui laoding 效果【防止重复上传文件】
2018/05/26 jQuery
React router动态加载组件之适配器模式的应用详解
2018/09/12 Javascript
vue component 中引入less文件报错 Module build failed
2019/04/17 Javascript
7个好用的JavaScript技巧分享(译)
2019/05/07 Javascript
Vue.js@2.6.10更新内置错误处机制Fundebug同步支持相应错误监控
2019/05/13 Javascript
vue中node_modules中第三方模块的修改使用详解
2019/05/31 Javascript
Vue 实例事件简单示例
2019/09/19 Javascript
使用JavaScrip模拟实现仿京东搜索框功能
2019/10/16 Javascript
vue-cli3项目升级到vue-cli4 的方法总结
2020/03/19 Javascript
用vue写一个日历
2020/11/02 Javascript
Python判断三段线能否构成三角形的代码
2020/04/12 Python
html5服务器推送_动力节点Java学院整理
2017/07/12 HTML / CSS
NBA欧洲商店(英国):NBA Europe Store UK
2018/07/27 全球购物
教师校本培训方案
2014/02/26 职场文书
班级课外活动总结
2014/07/09 职场文书
学生喝酒检讨书500字
2014/11/02 职场文书
2016七一建党节慰问信
2015/11/30 职场文书
Django+Celery实现定时任务的示例
2021/06/23 Python
如何更改Win11声音输出设备?Win11声音输出设备四种更改方法
2022/04/08 数码科技
Go微服务项目配置文件的定义和读取示例详解
2022/06/21 Golang