介绍Python的@property装饰器的用法


Posted in Python onApril 28, 2015

在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把成绩随便改:

s = Student()
s.score = 9999

这显然不合逻辑。为了限制score的范围,可以通过一个set_score()方法来设置成绩,再通过一个get_score()来获取成绩,这样,在set_score()方法里,就可以检查参数:

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了:

>>> s = Student()
>>> s.set_score(60) # ok!
>>> s.get_score()
60
>>> s.set_score(9999)
Traceback (most recent call last):
 ...
ValueError: score must between 0 ~ 100!

但是,上面的调用方法又略显复杂,没有直接用属性这么直接简单。

有没有既能检查参数,又可以用类似属性这样简单的方式来访问类的变量呢?对于追求完美的Python程序员来说,这是必须要做到的!

还记得装饰器(decorator)可以给函数动态加上功能吗?对于类的方法,装饰器一样起作用。Python内置的@property装饰器就是负责把一个方法变成属性调用的:

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本身又创建了另一个装饰器@score.setter,负责把一个setter方法变成属性赋值,于是,我们就拥有一个可控的属性操作:

>>> s = Student()
>>> s.score = 60 # OK,实际转化为s.set_score(60)
>>> s.score # OK,实际转化为s.get_score()
60
>>> s.score = 9999
Traceback (most recent call last):
 ...
ValueError: score must between 0 ~ 100!

注意到这个神奇的@property,我们在对实例属性操作的时候,就知道该属性很可能不是直接暴露的,而是通过getter和setter方法来实现的。

还可以定义只读属性,只定义getter方法,不定义setter方法就是一个只读属性:

class Student(object):

  @property
  def birth(self):
    return self._birth

  @birth.setter
  def birth(self, value):
    self._birth = value

  @property
  def age(self):
    return 2014 - self._birth

上面的birth是可读写属性,而age就是一个只读属性,因为age可以根据birth和当前时间计算出来。
小结

@property广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减少了出错的可能性。

Python 相关文章推荐
Python实现线程池代码分享
Jun 21 Python
使用Python &amp; Flask 实现RESTful Web API的实例
Sep 19 Python
python自动登录12306并自动点击验证码完成登录的实现源代码
Apr 25 Python
python对于requests的封装方法详解
Jan 03 Python
python3去掉string中的标点符号方法
Jan 22 Python
django 中QuerySet特性功能详解
Jul 25 Python
pytorch索引查找 index_select的例子
Aug 18 Python
在Python中画图(基于Jupyter notebook的魔法函数)
Oct 28 Python
Python调用Windows命令打印文件
Feb 07 Python
在PyTorch中使用标签平滑正则化的问题
Apr 03 Python
详解查看Python解释器路径的两种方式
Oct 15 Python
python 模拟登陆github的示例
Dec 04 Python
Pyhthon中使用compileall模块编译源文件为pyc文件
Apr 28 #Python
在Python中使用__slots__方法的详细教程
Apr 28 #Python
Python实现扫描局域网活动ip(扫描在线电脑)
Apr 28 #Python
python将文本转换成图片输出的方法
Apr 28 #Python
Python psutil模块简单使用实例
Apr 28 #Python
Python RuntimeError: thread.__init__() not called解决方法
Apr 28 #Python
Python标准库defaultdict模块使用示例
Apr 28 #Python
You might like
第七节--类的静态成员
2006/11/16 PHP
珊瑚虫IP库浅析
2007/02/15 PHP
解析PHP汉字转换拼音的类
2013/06/18 PHP
浅析php中抽象类和接口的概念以及区别
2013/06/27 PHP
php框架知识点的整理和补充
2021/03/01 PHP
JXTree对象,读取外部xml文件数据,生成树的函数
2007/04/02 Javascript
JS通过相同的name进行表格求和代码
2013/08/18 Javascript
jquery中EasyUI实现异步树
2015/03/01 Javascript
让JavaScript中setTimeout支持链式操作的方法
2015/06/19 Javascript
javascript匀速运动实现方法分析
2016/01/08 Javascript
jQuery判断是否存在滚动条的简单方法
2016/09/17 Javascript
JavaScript实现前端实时搜索功能
2020/03/26 Javascript
Vue数组更新及过滤排序功能
2017/08/10 Javascript
jquery-file-upload 文件上传带进度条效果
2017/11/21 jQuery
node.js使用express框架进行文件上传详解
2019/03/03 Javascript
vueScroll实现移动端下拉刷新、上拉加载
2019/03/22 Javascript
vue element-ui中table合计指定列求和实例
2020/11/02 Javascript
vue使用require.context实现动态注册路由
2020/12/25 Vue.js
python 生成不重复的随机数的代码
2011/05/15 Python
python redis 批量设置过期key过程解析
2019/11/26 Python
如何将 awk 脚本移植到 Python
2019/12/09 Python
Python爬虫爬取微博热搜保存为 Markdown 文件的源码
2021/02/22 Python
跑鞋、网球鞋、网球拍、服装及装备:Holabird Sports
2016/09/19 全球购物
美国受欢迎的眼影品牌:BH Cosmetics
2016/10/25 全球购物
教育专业自荐书范文
2013/12/17 职场文书
18岁生日感言
2014/01/12 职场文书
模特职业生涯规划范文
2014/02/26 职场文书
校车安全责任书
2014/08/25 职场文书
教师求职简历自我评价
2015/03/10 职场文书
2015年七夕情人节活动方案
2015/05/06 职场文书
2015年学校总务处工作总结
2015/05/19 职场文书
小马王观后感
2015/06/11 职场文书
党风廉洁教育心得体会
2016/01/20 职场文书
SpringBoot 拦截器妙用你真的了解吗
2021/07/01 Java/Android
「Manga Time Kirara MAX」2022年5月号封面公开
2022/03/21 日漫
JavaScript实现外溢动态爱心的效果的示例代码
2022/03/21 Javascript