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. 前端深入之css篇|link和@import到底有什么区别?

    写在前面 在真正的前端开发中,我们很少去写行内样式和内嵌样式,通常都是去引用外部样式. 而在我们学习之初的外部样式表都是用link引入的,但是当后来我们学习的逐渐深入,发现@import也可以引入样式 ...

  2. python爬虫——京东评论、jieba分词、wordcloud词云统计

    接上一章,动态页面抓取——抓取京东评论区内容. url=‘https://club.jd.com/comment/productPageComments.action?callback=fetchJS ...

  3. ['1', '2', '3'].map(parseInt) what & why ?

    这是今天在 Advanced-Frontend组织 看到一个比较有意思的题目.主要是讲JS的映射与解析早在 2013年, 加里·伯恩哈德就在微博上发布了以下代码段: ['10','10','10',' ...

  4. mac下ip地址重定向

    在终端临时使用最高权限用vim编辑/etc下的hosts文件,若提示Password: 输入开机登录密码并回车: yanguobindeMacBook-Pro:~ yanguobin$ sudo vi ...

  5. 低效sql语句执行缓慢引起的大量占用服务器的CPU问题处理 (优化心得)

    1> 2> 3> 4> 5>删除不良的执行计划后执行时间仍然有150s,这实在是太慢了,继续查看原sql代码,发现父表的关联条件放在了子查询里,这是应该避免的 调整原sq ...

  6. 我最推荐的一张Java后端学习路线图,Java工程师必备

    前言 学习路线图往往是学习一样技术的入门指南.网上搜到的Java学习路线图也是一抓一大把. 今天我只选一张图,仅此一图,足以包罗Java后端技术的知识点.所谓不求最好,但求最全,学习Java后端的同学 ...

  7. 神奇的Java僵尸(defunct)进程问题排查过程

    现象描述 大概1个月多以前 在启动脚本中增加了tail -f 用来启动后追踪日志判断是否启动成功 后发现无法执行shutdown.sh(卡住 利用curl) 然后无奈使用kill -9 但通过ps - ...

  8. 在web端使用html5访问远程桌面

    背景: 2019年12月5日,微软宣布放弃浏览器Edge,转而推出一款新的浏览器,而这款新浏览器将会采用谷歌的Chromium 内核... 好了,反正已经无力吐槽,微软烂尾的项目也不是一个两个了,之前 ...

  9. Cobalt Strike之信息收集、木马钓鱼

    System Profiler使用 System Profiler 模块,搜集目标的各类机器信息(操作系统版本,浏览器版本等) Attacks->web drive-by->System ...

  10. 【javascript 伪协议】小结

    [javascript 伪协议] 将javascript代码添加到客户端的方法是把它放置在伪协议说明符javascript:后的URL中.这个特殊的协议类型声明了URL的主体是任意的javascrip ...