python中@property装饰器的使用
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装饰器的使用的更多相关文章
- Python的property装饰器的基本用法
Python的@property装饰器用来把一个类的方法变成类的属性调用,然后@property本身又创建了另一个装饰器,用一个方法给属性赋值.下面是在类中使用了@property后,设置类的读写属性 ...
- 简单说明Python中的装饰器的用法
简单说明Python中的装饰器的用法 这篇文章主要简单说明了Python中的装饰器的用法,装饰器在Python的进阶学习中非常重要,示例代码基于Python2.x,需要的朋友可以参考下 装饰器对与 ...
- 【Python】python中的装饰器——@
对装饰器本来就一知半解的,今天终于弄清楚了,Python中的装饰器是对装饰者模式的很好运用,简化到骨子里了. python中为什么需要装饰器,看这里:http://www.cnblogs.com/hu ...
- Python 中实现装饰器时使用 @functools.wraps 的理由
Python 中使用装饰器对在运行期对函数进行一些外部功能的扩展.但是在使用过程中,由于装饰器的加入导致解释器认为函数本身发生了改变,在某些情况下——比如测试时——会导致一些问题.Python 通过 ...
- 写python中的装饰器
python中的装饰器主要用于在已有函数实现功能前附加需要输出的信息,下面将用实例展示我如何写装饰器. 首先分别尝试写装饰器装饰一个无参函数和一个有参函数(被装饰函数仅输出,无返回值情况下) def ...
- python中的装饰器decorator
python中的装饰器 装饰器是为了解决以下描述的问题而产生的方法 我们在已有的函数代码的基础上,想要动态的为这个函数增加功能而又不改变原函数的代码 例如有三个函数: def f1(x): retur ...
- [转载]Python使用@property装饰器--getter和setter方法变成属性
原贴:为什么Python不需要getter和setter getter 和 setter在java中被广泛使用.一个好的java编程准则为:将所有属性设置为私有的,同时为属性写getter和sette ...
- 【python】@property装饰器
Python内置的@property装饰器可以把类的方法伪装成属性调用的方式.也就是本来是Foo.func()的调用方法,变成Foo.func的方式.在很多场合下,这是一种非常有用的机制. class ...
- 三分钟搞定Python中的装饰器
python的装饰器是python的特色高级功能之一,言简意赅得说,其作用是在不改变其原有函数和类的定义的基础上,给他们增添新的功能. 装饰器存在的意义是什么呢?我们知道,在python中函数可以调用 ...
随机推荐
- vue自定义指令,比onerror更优雅的方式实现当图片加载失败时使用默认图,提供三种方法
首先,来看下效果图(演示一下图片正常加载与加载失败时的效果) 在线体验地址:https://hxkj.vip/demo/vueImgOnerror/ 一.常规方法解决 我们都知道,img标签支持one ...
- 31、vue-cli3引入封装svg图标
svg图标放大不失真,png会出现失真现象. 一.方法一 1.在对应vue项目里添加插件 vue add svg-sprite 输入 Y 2.在执行 npm install svgo svgo-loa ...
- 服务网关Spring Cloud Zuul
Spring Cloud Zuul 开发环境 idea 2019.1.2 jdk1.8.0_201 Spring Boot 2.1.9.RELEASE Spring Cloud Greenwich S ...
- springboot配置ehcache2.X缓存(@Cacheable等注解和手动操作缓存的工具类 支持element粒度的时间设置)
本文只写出一些注意事项和源码,请善用官方文档~ 注解实现 @Cacheable @CachePut @CacheEvit 启动类上加@EnableCaching就可以开启缓存 由文档可知,自动检测缓存 ...
- day 23
目录 面向对象总复习 面向对象总复习 面向过程编程思想: 核心是过程,过程指的是做事情的步骤,即先干什么再干什么. 基于该编程思想编程,就好比一条流水线,一种机械式的思维方式. 面向对象编程思 ...
- Selenium+PhantomJS使用时报错原因
运行下面代码:'''PhantomJS运用''' from selenium import webdriverimport time # 通过keys模拟键盘from selenium.webdriv ...
- Spring Cloud Alibaba(一) 如何使用nacos服务注册和发现
Nacos介绍 Nacos 致力于帮助您发现.配置和管理微服务.Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现.服务配置.服务元数据及流量管理. Nacos 帮助您更敏捷和容易地构 ...
- Cocos2d-x入门之旅[3]动作
Cocos通过动作(Action)可以让精灵动起来,把数个动作组成序列(Sequence)就能让精灵做出连续的动作,在动作中我们可以改变精灵的位置,旋转角度,缩放比例,等等 动作(Action) 首先 ...
- Python中的可变对象与不可变对象、浅拷贝与深拷贝
Python中的对象分为可变与不可变,有必要了解一下,这会影响到python对象的赋值与拷贝.而拷贝也有深浅之别. 不可变对象 简单说就是某个对象存放在内存中,这块内存中的值是不能改变的,变量指向这块 ...
- Windows渗透测试中wmi的利用
0x01 关于WMI WMI可以描述为一组管理Windows系统的方法和功能.我们可以把它当作API来与Windows系统进行相互交流.WMI在渗透测试中的价值在于它不需要下载和安装, 因为WMI是W ...