Python11--装饰器
2020-08-31 本文已影响0人
伊洛的小屋
1.装饰器定义
-
装饰器
本质上是一个函数
,可以接受一个函数
作为参数
2.装饰器简单的例子
- 承接之前的内容,英雄释放火焰技能。打印出英雄释放技能的时间
#!/usr/bin/python
from datetime import datetime
def release_skills(hero):
def release_skill(*skill, **skills):
print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
return hero(*skill, **skills)
return release_skill
@release_skills
def hero(name, skill):
return (name + '-->'+'释放技能:'+ skill)
print(hero('关羽', 'fire'))
print(hero.__name__)
- 如上,
release_skills
装饰器负责打印释放技能的时间
(yiluo) ➜ Code python hero.py
2019-12-12 11:11:49
关羽-->释放技能:fire
release_skill
- 我们运行
hero
函数的时候,同时打印出了英雄释放火焰技能的时间 - 可是我们发现了一个比较严重的问题,
hero
函数应变成了release_skill
函数了,看上面的代码,确实hero
已经被release_skill
改变了 - 那如何解决这个被改变的问题呢? 总不能用完装饰器,被装饰的函数已经不是之前的函数吧,还好
Python
提供了方法解决这个问题
# 作者:伊洛Yiluo 公众号:伊洛的小屋
# 个人主页:https://yiluotalk.com/
# 博客园:https://www.cnblogs.com/yiluotalk/
#!/usr/bin/python
from datetime import datetime
from functools import wraps
def release_skills(hero):
@wraps(hero)
def release_skill(*skill, **skills):
print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
return hero(*skill, **skills)
return release_skill
@release_skills
def hero(name, skill):
return (name + '-->'+'释放技能:'+ skill)
print(hero('关羽', 'fire'))
print(hero.__name__)
- 上面的代码用到了
wraps()
,然后我们运行一下看下结果函数是否被改变
(yiluo) ➜ Code python hero.py
2019-12-12 11:25:38
关羽-->释放技能:fire
hero
- 函数依旧是
hero
,看来是完美解决了这个问题 -
@
是Python
提供的语法糖,语法糖指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用
3.property 装饰器
#!/usr/bin/env python3
class Animal:
def __init__(self):
self.age = 3
if __name__ == "__main__":
cat = Animal()
print(cat.age)
cat.age = 'age'
print(cat.age)
- 执行结果
➜ code python3 demo.py
3
age
- 以看到如果 age 属性值可以被公开访问,用户赋值为字符串,很明显这不符合实际情况
#!/usr/bin/env python3
class Animal:
def __init__(self):
self.__age = 3
def get_age(self):
return self.__age
def set_age(self, value):
if isinstance(value, int):
self.__age = value
else:
raise ValueError
if __name__ == "__main__":
cat = Animal()
print(cat.get_age)
cat.set_age('age')
- 执行结果
Traceback (most recent call last):
File "demo.py", line 18, in <module>
cat.set_age('age')
File "demo.py", line 12, in set_age
raise ValueError
ValueError
- @property 装饰器可以将一个方法变成一个属性来使用,通过 @property 装饰器可以获得和修改对象的某一个属性。
- 使用 @property 装饰器的方法如下:
1.只有 @property 表示只读
2.同时有 @property 和 @.setter 表示可读可写
3.同时有 @property、@.setter、和 @.deleter 表示可读可写可删除
4.@property 必须定义在 @.setter 的前面
5.类必须继承 object 父类,否则 @property 不会生效
#!/usr/bin/env python3
class Animal:
def __init__(self):
self.__age = 3
@property
def age(self):
return self.__age
@age.setter
def age(self, value):
if isinstance(value, int):
self.__age = value
else:
raise ValueaError
@age.deleter
def age(self):
print('delete age')
del self.__age
if __name__ == "__main__":
cat = Animal()
print(cat.age)
cat.age = 6
print(cat.age)
del cat.age
print(cat.age)
- 执行结果
➜ code python3 demo.py
3
6
delete age
Traceback (most recent call last):
File "demo.py", line 26, in <module>
print(cat.age)
File "demo.py", line 8, in age
return self.__age
AttributeError: 'Animal' object has no attribute '_Animal__age'
- 从这个简单的例子中我们可以发现 age 由一个函数转变为一个属性,并且通过增加一个 setter 函数的方式来支持 age 的设置。通过 property 和 setter ,可以有效地实现 get_age(获取对象的属性) 和 set_age(设置对象的属性)这两个操作,而不需要直接将内部的 __age 属性暴露出来,同时可以在 setter 函数中对设置的参数进行检查,避免了直接对 __age 内部属性进行赋值的潜在风险
欢迎下方【戳一下】【点赞】
Author:伊洛Yiluo
愿你享受每一天,Just Enjoy !