介绍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中的应用之translate和maketrans用法详解
Aug 27 Python
python基于itchat实现微信群消息同步机器人
Feb 27 Python
python使用生成器实现可迭代对象
Mar 20 Python
Python openpyxl 遍历所有sheet 查找特定字符串的方法
Dec 10 Python
centos6.5安装python3.7.1之后无法使用pip的解决方案
Feb 14 Python
解决Python安装时报缺少DLL问题【两种解决方法】
Jul 15 Python
Python代码块及缓存机制原理详解
Dec 13 Python
使用Python爬虫库BeautifulSoup遍历文档树并对标签进行操作详解
Jan 25 Python
使用IPython或Spyder将省略号表示的内容完整输出
Apr 20 Python
Python ini文件常用操作方法解析
Apr 26 Python
python爬虫可以爬什么
Jun 16 Python
python使用numpy中的size()函数实例用法详解
Jan 29 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
thinkphp实现把数据库中的列的值存到下拉框中的方法
2017/01/20 PHP
PHP递归统计系统中代码行数
2019/09/19 PHP
js返回上一页并刷新代码整理
2012/12/21 Javascript
让javascript加载速度倍增的方法(解决JS加载速度慢的问题)
2014/12/12 Javascript
html的DOM中document对象forms集合用法实例
2015/01/21 Javascript
JavaScript性能优化之小知识总结
2015/11/20 Javascript
使用Sticky组件实现带sticky效果的tab导航和滚动导航的方法
2016/03/22 Javascript
Javascript 6里的4个新语法
2016/08/25 Javascript
利用n 升级工具升级Node.js版本及在mac环境下的坑
2017/02/15 Javascript
Vue.js父与子组件之间传参示例
2017/02/28 Javascript
Bootstrap输入框组件使用详解
2017/06/09 Javascript
Vue中引入样式文件的方法
2017/08/18 Javascript
vue.js动画中的js钩子函数的实现
2018/07/06 Javascript
IE8中jQuery.load()加载页面不显示的原因
2018/11/15 jQuery
每天学点Vue源码之vm.$mount挂载函数
2019/03/11 Javascript
vue.js实现数据库的JSON数据输出渲染到html页面功能示例
2019/08/03 Javascript
vue实现滚动鼠标滚轮切换页面
2020/12/13 Vue.js
[00:12]DAC SOLO赛卫冕冠军 VG.Paparazi灬展现SOLO技巧
2018/04/06 DOTA
[02:03]风行者至宝清风环佩外观展示
2020/09/05 DOTA
详解Python中的join()函数的用法
2015/04/07 Python
使用Python制作获取网站目录的图形化程序
2015/05/04 Python
Django2.1.3 中间件使用详解
2018/11/26 Python
安装Pycharm2019以及配置anconda教程的方法步骤
2019/11/11 Python
windows10 pycharm下安装pyltp库和加载模型实现语义角色标注的示例代码
2020/05/07 Python
opencv 图像加法与图像融合的实现代码
2020/07/08 Python
Python内置函数及功能简介汇总
2020/10/13 Python
不可轻视HTML5!App三年内将被html5顶替彻底消失
2015/11/18 HTML / CSS
应用电子技术专业个人求职信
2013/09/21 职场文书
服务员岗位职责
2014/01/29 职场文书
简历中自我评价怎么写
2014/02/12 职场文书
代理协议书范本
2014/04/22 职场文书
社区挂职锻炼个人工作总结
2015/10/23 职场文书
廉洁自律承诺书2016
2016/03/25 职场文书
Java字符串逆序方法详情
2022/03/21 Java/Android
原生JS实现分页
2022/04/19 Javascript
win10输入法不见了只能打出字母怎么解决?
2022/08/05 数码科技