介绍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抓取网页中图片并保存到本地
Dec 01 Python
Python http接口自动化测试框架实现方法示例
Dec 06 Python
Django外键(ForeignKey)操作以及related_name的作用详解
Jul 29 Python
python爬虫模拟浏览器的两种方法实例分析
Dec 09 Python
Python3搭建http服务器的实现代码
Feb 11 Python
python实现俄罗斯方块游戏(改进版)
Mar 13 Python
Python3标准库之dbm UNIX键-值数据库问题
Mar 24 Python
解决django的template中如果无法引用MEDIA_URL问题
Apr 07 Python
使用Dajngo 通过代码添加xadmin用户和权限(组)
Jul 03 Python
python 下载文件的多种方法汇总
Nov 17 Python
python3代码输出嵌套式对象实例详解
Dec 03 Python
如何利用python 读取配置文件
Jan 06 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下intval()和(int)转换使用与区别
2008/07/18 PHP
教你如何在CI框架中使用 .htaccess 隐藏url中index.php
2014/06/09 PHP
php判断两个浮点数是否相等的方法
2015/03/14 PHP
PHP浮点数精度问题汇总
2015/05/13 PHP
php实现window平台的checkdnsrr函数
2015/05/27 PHP
YII2框架中查询生成器Query()的使用方法示例
2020/03/18 PHP
javascript生成/解析dom的CDATA类型的字段的代码
2007/04/22 Javascript
js中字符替换函数String.replace()使用技巧
2011/08/14 Javascript
使用jquery读取html5 localstorage的值的方法
2013/01/04 Javascript
用javascript添加控件自定义属性解析
2013/11/25 Javascript
JavaScript charCodeAt方法入门实例(用于取得指定位置字符的Unicode编码)
2014/10/17 Javascript
javascript巧用eval函数组装表单输入项为json对象的方法
2015/11/25 Javascript
由浅入深讲解Javascript继承机制与simple-inheritance源码分析
2015/12/13 Javascript
JavaScript function函数种类详解
2016/02/22 Javascript
JavaScript中误用/g导致的正则test()无法正确重复执行的解决方案
2016/07/27 Javascript
JS实用的带停顿的逐行文本循环滚动效果实例
2016/11/23 Javascript
jQuery实现遮罩层登录对话框
2016/12/29 Javascript
angular十大常见问题
2017/03/07 Javascript
JS操作xml对象转换为Json对象示例
2017/03/25 Javascript
Angular中自定义Debounce Click指令防止重复点击
2017/07/26 Javascript
Vue 兄弟组件通信的方法(不使用Vuex)
2017/10/26 Javascript
在vue-cli 3中给stylus、sass样式传入共享的全局变量
2019/08/12 Javascript
Vue根据条件添加click事件的方式
2019/11/09 Javascript
vue实现分页加载效果
2019/12/24 Javascript
Python中使用ConfigParser解析ini配置文件实例
2014/08/30 Python
Python中字典创建、遍历、添加等实用操作技巧合集
2015/06/02 Python
Python PIL读取的图像发生自动旋转的实现方法
2019/07/05 Python
python模块导入的方法
2019/10/24 Python
浅谈tensorflow中dataset.shuffle和dataset.batch dataset.repeat注意点
2020/06/08 Python
jupyter notebook 写代码自动补全的实现
2020/11/02 Python
婴儿鞋,独特的婴儿服装和配件:Zutano
2018/11/03 全球购物
毕业设计计划书
2014/01/09 职场文书
出资证明书范本(标准版)
2014/09/24 职场文书
Python机器学习之PCA降维算法详解
2021/05/19 Python
Python中Selenium对Cookie的操作方法
2021/07/09 Python
Python编写车票订购系统 Python实现快递收费系统
2022/08/14 Python