介绍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统计文件行数示例分享
Feb 21 Python
Python里disconnect UDP套接字的方法
Apr 23 Python
TensorFlow打印tensor值的实现方法
Jul 27 Python
对Python 内建函数和保留字详解
Oct 15 Python
Python 通过requests实现腾讯新闻抓取爬虫的方法
Feb 22 Python
搞清楚 Python traceback的具体使用方法
May 13 Python
pandas 对日期类型数据的处理方法详解
Aug 08 Python
python+jinja2实现接口数据批量生成工具
Aug 28 Python
Python加密模块的hashlib,hmac模块使用解析
Jan 02 Python
Windows下Pycharm远程连接虚拟机中Centos下的Python环境(图文教程详解)
Mar 19 Python
Python使用plt.boxplot() 参数绘制箱线图
Jun 04 Python
Python list列表删除元素的4种方法
Nov 01 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
最新的php 文件上传模型,支持多文件上传
2009/08/13 PHP
PHP的autoload自动加载机制使用说明
2010/12/28 PHP
注释PHP和html混合代码的小技巧(分享)
2016/11/03 PHP
php识别翻转iphone拍摄的颠倒图片
2018/05/17 PHP
PHP实现的只保留字符串首尾字符功能示例【隐藏部分字符串】
2019/03/11 PHP
php使用redis的有序集合zset实现延迟队列应用示例
2020/02/20 PHP
JavaScript实现的简单拖拽效果
2015/06/01 Javascript
js实现随屏幕滚动的带缓冲效果的右下角广告代码
2015/09/04 Javascript
由浅入深讲解Javascript继承机制与simple-inheritance源码分析
2015/12/13 Javascript
JavaScript实现搜索框的自动完成功能(一)
2016/02/25 Javascript
json格式的javascript对象用法分析
2016/07/04 Javascript
vue多级多选菜单组件开发
2020/09/08 Javascript
JQuery ZTree使用方法详解
2017/01/07 Javascript
JS实现小球的弹性碰撞效果
2017/11/11 Javascript
layui实现下拉复选功能的例子(包括数据的回显与上传)
2019/09/24 Javascript
JavaScript定时器使用方法详解
2020/03/26 Javascript
[46:00]DOTA2上海特级锦标赛主赛事日 - 2 胜者组第一轮#4EG VS Fnatic第一局
2016/03/03 DOTA
python 将字符串转换成字典dict
2013/03/24 Python
Python os模块介绍
2014/11/30 Python
详解Python多线程Selenium跨浏览器测试
2017/04/01 Python
Python正则抓取网易新闻的方法示例
2017/04/21 Python
Python正则表达式非贪婪、多行匹配功能示例
2017/08/08 Python
AI人工智能 Python实现人机对话
2017/11/13 Python
利用python解决mysql视图导入导出依赖的问题
2017/12/17 Python
Python3.6通过自带的urllib通过get或post方法请求url的实例
2018/05/10 Python
python自动化实现登录获取图片验证码功能
2019/11/20 Python
python实现输入的数据在地图上生成热力图效果
2019/12/06 Python
Python更新所有已安装包的操作
2020/02/13 Python
jupyter 导入csv文件方式
2020/04/21 Python
表达自我的市场:Society6
2018/08/01 全球购物
Bibloo罗马尼亚网站:女装、男装、童装及鞋子和配饰
2019/07/20 全球购物
社团活动总结报告
2014/06/27 职场文书
优秀教师事迹材料
2014/12/15 职场文书
招商银行收入证明
2015/06/17 职场文书
新闻稿标题
2015/07/18 职场文书
数据库连接池
2021/04/06 MySQL