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. .Net Core自动化部署系列(二):使用Jenkins打造镜像发布流水线

    一.简介 之前写过一篇关于Jenkins搭配GitLab实现.net core项目自动发布到IIS的博文,比较简单哈,只是个Demo.本篇我们将会使用Jenkins搭配GitLab实现镜像的自动打包和 ...

  2. yii中缓存(cache)详解 - 彼岸あ年華ツ

    缓存是用于提升网站性能的一种即简单又有效的途径.通过存储相对静态的数据至缓存以备所需,我们可以省去生成 这些数据的时间.在 Yii 中使用缓存主要包括配置和访问缓存组件 . 内部方法 一.缓存配置: ...

  3. xpath语法分享

    # xpath语法: ## 使用方式: 使用//获取整个页面当中的元素,然后写标签名,然后再写谓词进行提取.比如: ``` //div[@class='abc'] ``` ## 需要注意的知识点: 1 ...

  4. springboot与docker整合

    一.springboot与docker整合 a.创建Dockerfile FROM java MAINTAINER "Wing"<1561815137@qq.com> ...

  5. 报错com.neenbedankt.android-apt not found如何解决

    apply plugin: 'com.neenbedankt.android-apt' 在moudle中build.gradle文件内有应用此插件,编译时报错 检查Project中build.grad ...

  6. Node.js入门教程 第三篇 (模块及路由)

    Node.js的模块 Node.js的模块与传统面向对象的类(class)不完全相同.Node.js认为文件即模块,即一个文件是一个模块.单一文件一般只专注做一件事情,保证了代码的简洁性. 创建模块: ...

  7. react 首屏性能优化

    首屏优化点:1.加载包(bundle.js)文件的大小,越小,首屏渲染速度越快 (按需加载) 2.优先渲染用户直观看到的页面部分(懒加载) 技术点:react-loadable . react-laz ...

  8. python编程基础之三十二

    成员方法:成员方法就是一个函数,只是作用域在类内,并且第一个参数必须是self,self代表当前对象, class Dog(object): def bark(self): #成员方法,第一个参数必须 ...

  9. bugku 程序员本地网站

    提示从本地访问,怎样让服务器认为你是从本地进行访问的: 使用burp抓包并在包中进行修改加入X-Forwarded-For: 127.0.0.1 X-Forwarded-For: 简称XFF头,它代表 ...

  10. Spring基础(二)

    一.使用注解配置Spring 1.1步骤 --配置文件中,指明注解位置 --要用的地方打上注解 --改对象的作用范围(修改掉默认的单例,变多例) --属性的注入(两种) 使用的反射实现 set方法实现 ...