要了解@property的用途,首先要了解如何创建一个属性。

一般而言,属性都通过__init__方法创建,比如:

 class Student(object):
def __init__(self,name,score):
self.name=name
self.score=score

创建实例,运行结果:

 tim=Student('Tim',97)
tim.score=100
tim.score
100
mary=Student('Mary',90)
mary.score
90

但是这样子有2个坏处:

1.__init__ 中定义的属性是可变的,如果一个系统的开发人员在知道属性名的情况下,就可以进行随意更改(尽管可能是在无意识的情况下),如果一不小心篡改了,后台排查很难!

2.不利于进行参数检查,比如:score属性范围本该是[0,100],但如果输成了1000也不会报错。

因此,一个标准的创建属性流程如下:

1.定义三个跟属性(本例中是score)相关的函数:

get(用于返回score属性)

set(用于设定score属性)

del(用于删除score属性)

在set函数中,可以添加一些取值范围,比如[0,100].此外,为了私有化属性,前面可以加上__。

这样就做到了既能通过创建实例设定属性,又不让开发人员轻易修改score属性。

如下所示:

 class Student(object):
def getScore(self):
return self.__score def setScore(self,score):
if score>100 or score<0:
raise ValueError ('score is out of range.')
else:
self.__score=score def delScore(self):
del self.__score

这样,一旦score取值不在设定范围内,就会报错!

创建一个实例,能够正常运行:

 Mary=Student()
Mary.setScore(90)
Mary.getScore()
90

但是,通过方法getScore()查看分数似乎还是有点繁琐,能不能把它当作一个属性去调用呢?至少调用不需要输入()嘛!

当然是可以的。

办法就是通过装饰器:@property

通过给getScore,setScore,delScore三个方法分别添加三个装饰器,就可以直接把这三个方法作为属性去调用了!

如下所示:

 class Student(object):
@property
def getScore(self):
return self.__score
@getScore.setter
def setScore(self,score):
if score>100 or score<0:
raise ValueError ('score is out of range.')
else:
self.__score=score
@getScore.deleter
def delScore(self):
del self.__score
 tim=Student()
tim.setScore=90
tim.getScore
90

非常神奇!方法居然变成了属性,为什么呢?

因为装饰器@property本质上是一个property()函数,property()函数也是一个装饰器。

一般的装饰器是用在普通函数上,而@property是用在类内的方法上。

property()函数包含了三个部分:getter,setter,deleter。

因为setter和deleter是property()的第二和第三个参数,不能直接套用@语法。

因此,本质上@property相当于getter部分,@setScore.setter相当于setter部分,@delScore.deleter相当于deleter部分。

所以,上面的代码本质上等价于:

 class Student(object):
def getScore(self):
return self.__score def setScore(self,score):
if score>100 or score<0:
raise ValueError ('score is out of range.')
else:
self.__score=score def delScore(self):
del self.__score score=property(getScore,setScore,delScore,'description')

最后,为了函数名美观,可以把函数名字改成Score():

 class Student(object):
@property
def Score(self):
return self.__score
@Score.setter
def Score(self,score):
if score>100 or score<0:
raise ValueError ('score is out of range.')
else:
self.__score=score
@Score.deleter
def delScore(self):
del self.__score tim=Student()
tim.Score=90
tim.Score
90

几篇个人觉得写的比较清楚的文章:

http://www.runoob.com/python/python-func-property.html

https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143186781871161bc8d6497004764b398401a401d4cce000

https://www.cnblogs.com/cicaday/p/python-decorator.html

Python中的@property装饰器的更多相关文章

  1. 第7.26节 Python中的@property装饰器定义属性访问方法getter、setter、deleter 详解

    第7.26节 Python中的@property装饰器定义属性访问方法getter.setter.deleter 详解 一.    引言 Python中的装饰器在前面接触过,老猿还没有深入展开介绍装饰 ...

  2. Python中利用函数装饰器实现备忘功能

    Python中利用函数装饰器实现备忘功能 这篇文章主要介绍了Python中利用函数装饰器实现备忘功能,同时还降到了利用装饰器来检查函数的递归.确保参数传递的正确,需要的朋友可以参考下   " ...

  3. python 中多个装饰器的执行顺序

    python 中多个装饰器的执行顺序: def wrapper1(f1): print('in wrapper1') def inner1(*args,**kwargs): print('in inn ...

  4. python中面向对象之装饰器

    python面向对象内置装饰器property,staticmethod,classmethod的使用 @property 装饰器作用及使用 作用:面向对象中的方法伪装成属性 使用如下: class ...

  5. 面向对象中的property装饰器讲解

    面向对象中可以用property来修饰我们的函数,必须下面的例子 class Test(object): def __init__(self,name): self.name = name @prop ...

  6. Python中的各种装饰器详解

    Python装饰器,分两部分,一是装饰器本身的定义,一是被装饰器对象的定义. 一.函数式装饰器:装饰器本身是一个函数. 1.装饰函数:被装饰对象是一个函数 [1]装饰器无参数: a.被装饰对象无参数: ...

  7. 谈谈Python中的decorator装饰器,如何更优雅的重用代码

    众所周知,Python本身有很多优雅的语法,让你能用一行代码写出其他语言很多行代码才能做的事情,比如: 最常用的迭代(eg: for i in range(1,10)), 列表生成式(eg: [ x* ...

  8. Python中的单例模式——装饰器实现剖析

    Python中单例模式的实现方法有多种,但在这些方法中属装饰器版本用的广,因为装饰器是基于面向切面编程思想来实现的,具有很高的解耦性和灵活性. 单例模式定义:具有该模式的类只能生成一个实例对象. 先将 ...

  9. python中闭包和装饰器的理解(关于python中闭包和装饰器解释最好的文章)

    转载:http://python.jobbole.com/81683/ 呵呵!作为一名教python的老师,我发现学生们基本上一开始很难搞定python的装饰器,也许因为装饰器确实很难懂.搞定装饰器需 ...

随机推荐

  1. HVR数据复制软件部署之(一)--HUB端部署

    HVR数据复制软件部署之(一)--HUB端部署 本文环境: OS: RHEL5.9 x86-64bit DB: Oracle 12.1.0.2 x86-64bit HVR:highgohvr-4.7. ...

  2. 常用的java方法,为程序添点小功能

    一.生成随机数 Random类使用示例 使用Random类,一般是生成指定区间的随机数字,下面就一一介绍如何生成对应区间的随机数字.以下生成随机数的代码均使用以下Random对象r进行生成: Rand ...

  3. android studio中xml文件代码提示问题

    在系统控件中输入“a”能提示出android:id等所有属性.而在第三方库的控件中输入“a”只会提示“appNs”,但如果手动写app:id="@+id/aaa"系统也是可以识别的 ...

  4. IEC61131-3——数据类型

    1. 摘要 列出IEC61131-3支持的几种常用数据类型. 2. 内容 使用USB-CAN接口卡调试从站,SDO发送使用的功能码与字节的关系如下. 2f表示8位,2b表示16位,23表示32位数据. ...

  5. Polymorphism (C# Programming Guide)

    https://msdn.microsoft.com/en-us/library/ms173152.aspx Polymorphism is often referred to as the thir ...

  6. [python基础] celery beat/task/flower解析

    一.Celery 介绍 Celery 是一个强大的分布式任务队列,它可以让任务的执行完全脱离主程序,甚至可以被分配到其他主机上运行.我们通常使用它来实现异步任务( async task )和定时任务( ...

  7. DStream 转换操作------有状态转换操作

    import org.apache.spark.SparkConf import org.apache.spark.streaming.{Seconds, StreamingContext} obje ...

  8. [Swift通天遁地]二、表格表单-(10)快速添加日期选择/多选/动作表单/地图等自定义表单

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  9. 免费开源ERP成功案例分享:化学之家通过Odoo实现工业互联网转型

    本文来自<开源智造Odoo客户成功案例采访实录>的精选内容章节.请勿转载.欢迎您反馈阅读意见. 客户地区:江苏常州 客户名称:化学之家(中外合资) 所属行业:化工制造(工业) 实施模块:销 ...

  10. JS 正则查找与替换

    JS正则查找与替换 一.前提/背景 今天遇到个问题,需要替换字符串中部分字符,这些字符相对整个字符串而言,与其他子字符串类似,无法单独提出:重要的是,该字符串是动态的生成的,就像我们日常看到的网页Ur ...