python中@property装饰器的使用

1、引出问题

在为一个类实例绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把成绩随便改,甚至类型错误都可以。

class Student(object):

    def __init__(self, score):
self.score = score if __name__ == '__main__':
s = Student(100)
print(s.score)
s.score = 50
print(s.score)
s.score = 'abc'
print(s.score) ------------------------------ >>> 100
>>> 50
>>> abc

2、初步改善

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

class Student(object):

    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 def get_score(self):
return self._score if __name__ == '__main__':
s = Student()
s.set_score(50)
print(s.get_score())
s.set_score('abc') ------------------------------ >>> 50
>>> Traceback (most recent call last):
File "/Users/luyuze/projects/myflask/App/test.py", line 18, in <module>
s.set_score('abc')
File "/Users/luyuze/projects/myflask/App/test.py", line 6, in set_score
raise ValueError('score must be an integer !')
ValueError: score must be an integer !

现在,对任意的Student实例进行操作,就不能随心所欲的设置score了。

3、使用@property

上面的调用方法虽然已经可以实现相关功能,但是使用起来略显复杂,设置和获取属性都需要通过调用方法来实现,没有直接用属性这么简洁明了。

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

下面,我们就使用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 if __name__ == '__main__':
s = Student()
s.score = 50 # 实际转化为s.set_score()
print(s.score) # 实际转化为s.get_score()
s.score = 101 ------------------------------ >>> 50
>>> Traceback (most recent call last):
File "/Users/luyuze/projects/myflask/App/test.py", line 21, in <module>
s.score = 101
File "/Users/luyuze/projects/myflask/App/test.py", line 13, in score
raise ValueError('score must between 0 - 100 !')
ValueError: score must between 0 - 100 !

4、解析@property

@property的实现比较复杂,我们先考察如何使用,把一个getter方法变成属性,只需要加上@property就可以了,此时,@property本身又创建了另一个装饰器@score.setter,负责把一个setter方法变成属性赋值,于是,我们就拥有了如上例子中的属性操作。

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

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

import datetime

class Student(object):

    @property
def birth(self):
return self._birth @birth.setter
def birth(self, value):
if not isinstance(value, int):
raise ValueError('birth must be an integer !')
self._birth = value @property
def age(self):
return datetime.datetime.now().year - self._birth if __name__ == '__main__':
s = Student()
s.birth = 1995
print(s.age)
s.age = 25 ------------------------------ >>> 24
>>> Traceback (most recent call last):
File "/Users/luyuze/projects/myflask/App/test.py", line 25, in <module>
s.age = 25
AttributeError: can't set attribute

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

5、总结

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

python中@property装饰器的使用的更多相关文章

  1. Python的property装饰器的基本用法

    Python的@property装饰器用来把一个类的方法变成类的属性调用,然后@property本身又创建了另一个装饰器,用一个方法给属性赋值.下面是在类中使用了@property后,设置类的读写属性 ...

  2. 简单说明Python中的装饰器的用法

    简单说明Python中的装饰器的用法 这篇文章主要简单说明了Python中的装饰器的用法,装饰器在Python的进阶学习中非常重要,示例代码基于Python2.x,需要的朋友可以参考下   装饰器对与 ...

  3. 【Python】python中的装饰器——@

    对装饰器本来就一知半解的,今天终于弄清楚了,Python中的装饰器是对装饰者模式的很好运用,简化到骨子里了. python中为什么需要装饰器,看这里:http://www.cnblogs.com/hu ...

  4. Python 中实现装饰器时使用 @functools.wraps 的理由

    Python 中使用装饰器对在运行期对函数进行一些外部功能的扩展.但是在使用过程中,由于装饰器的加入导致解释器认为函数本身发生了改变,在某些情况下——比如测试时——会导致一些问题.Python 通过  ...

  5. 写python中的装饰器

    python中的装饰器主要用于在已有函数实现功能前附加需要输出的信息,下面将用实例展示我如何写装饰器. 首先分别尝试写装饰器装饰一个无参函数和一个有参函数(被装饰函数仅输出,无返回值情况下) def ...

  6. python中的装饰器decorator

    python中的装饰器 装饰器是为了解决以下描述的问题而产生的方法 我们在已有的函数代码的基础上,想要动态的为这个函数增加功能而又不改变原函数的代码 例如有三个函数: def f1(x): retur ...

  7. [转载]Python使用@property装饰器--getter和setter方法变成属性

    原贴:为什么Python不需要getter和setter getter 和 setter在java中被广泛使用.一个好的java编程准则为:将所有属性设置为私有的,同时为属性写getter和sette ...

  8. 【python】@property装饰器

    Python内置的@property装饰器可以把类的方法伪装成属性调用的方式.也就是本来是Foo.func()的调用方法,变成Foo.func的方式.在很多场合下,这是一种非常有用的机制. class ...

  9. 三分钟搞定Python中的装饰器

    python的装饰器是python的特色高级功能之一,言简意赅得说,其作用是在不改变其原有函数和类的定义的基础上,给他们增添新的功能. 装饰器存在的意义是什么呢?我们知道,在python中函数可以调用 ...

随机推荐

  1. 模拟实现JSON.stringiry 的格式化输出

    前言 这是一道笔试题,要求模拟实现JSON.stringiry 的格式化输出,按照层级缩进,输出易读格式,即完成以下方法 JSON.stringify(jsObj, null, 4); // 缩进4个 ...

  2. API文档注释 Javadoc

    阅读API文档 JDK包结构 JDK包是由sun开发的一组已经实现的类库,.JDK根据提供的功能不同,将类库划分为若干个包,比如用于操作输入输出的  java.io包,java程序语言设计基础类的   ...

  3. 品Spring:关于@Scheduled定时任务的思考与探索,结果尴尬了

    非Spring风格的代码与Spring的结合 现在的开发都是基于Spring的,所有的依赖都有Spring管理,这没有问题. 但是要突然写一些非Spring风格的代码时,可能会很不习惯,如果还要和Sp ...

  4. 2.css3表示颜色的几种方式

    1.css3中表示颜色的几种方式: ⑴颜色名称.十六进制.RGB方式: ⑵RGBA方式:新增了alpha参数,介于0.0(完全透明)到1.0(完全不透明)之间: ⑶HSL方式:分别表示色调.饱和度.亮 ...

  5. 大神都在用的yum源

    本文原创首发于公众号:编程三分钟 yum 命令的使用 yum命令天天都在用,都快用烂了,但是很多人不知道为什么只要联网,yum命令就能像老奶奶手中的魔法棒一样,随心所欲的下载到想到的包. 比如你想装个 ...

  6. Aria2 1.35.0,更新,测试,发布

    在上一篇: 有哪些便宜还好用的东西,买了就感觉得了宝一样? 结尾提到了Tatsuhiro Tsujikawa的aria2计划在10月更新一个新的版本 今天趁着雨后明月挂天,开始了简单的更新 虽然在半年 ...

  7. linux分区与挂载

    分区是将一个硬盘驱动器分成若干个逻辑驱动器,分区是把硬盘连续的区块当做一个独立的磁盘使用.分区表是一个硬盘分区的索引,分区的信息都会写进分区表.通常情况下,为磁盘分区通常使用fdisk,它是对基于MB ...

  8. 总结下var、let 和 const 的区别

    一.var变量 <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...

  9. 基于STM32F429和HAL库的CAN收发例程

    1.CAN协议介绍 CAN 是 Controller Area Network 的缩写(以下称为 CAN),是 ISO 国际标准化的串行通信协议.在当前的汽车产业中,出于对安全性.舒适性.方便性.低公 ...

  10. c语言程序设计2

    c语言秋季作业2 问题 答案 这个作业属于哪个课程 C语言程序设计Ⅰ 这个作业要求在哪里 [c语言博客作业02](https://edu.cnblogs.com/campus/zswxy/SE2019 ...