装饰器
一、什么是装饰器?
器 就是工具 可以用函数定义
装饰 为其他事物添加功能
合到一起可以理解成是定义一个函数来装饰其他函数。给其他函数添加额外的功能。
装饰器 的使用满足开放封闭原则
即对于代码功能的拓展是开放的
对于修改源代码是封闭的
合到一起就是不能改函数的调用方式,和原函数的代码,但是要增加原函数的功能。
二、装饰器怎么定义?
from functools import wraps
def outter(func):
@wraps(func) # 将wrapper函数伪装成func函数的工具,除了返回值,参数以外,包括func的内置属性__name__,__file__等等都伪装成一样的。
def wrapper(*args,**kwargs): # 确保wrapper的参数,返回值,调用方式都跟func一模一样,但是可以增加一些功能
# 功能可以增加在这里
res = func(*args,**kwargs)
return res
return wrapper
==============================> 下面是函数的调用阶段啦
func = outter(func) # 返回值就是wrapper函数的内存地址,之后再加上括号就可以实现在不改变func函数的代用方式,和代码的情况下,实现对于func功能的增加。这就是无参装饰器的模板啦!
python给我们提供了语法糖,准许我们将func = outter(func) 这样的语句,简写成
@outter # 在被装饰的函数上面声明装饰器即可实现为函数加上功能,可以制作一些认证装饰器,时间装饰器,等等
def func(*args,**kwargs):
pass
==================================================》 下面是有参装饰器啦~
from functools import wraps
def code(x):
def outter(func):
@wraps(func)
def wrapper(*args,**kwargs): # 确保wrapper的参数,返回值,调用方式都跟func一模一样,但是可以增加一些功能
# 功能可以增加在这里
res = func(*args,**kwargs)
return res
return wrapper
return outter
==============================> 下面是函数的调用阶段啦
受语法糖的限制,我们不能再outter函数中在增加参数了,但是如果确实还有需要传进来的变量参数呢,我们可以通过再嵌套一层的方法给函数传参。
outter = code(x)
无参装饰器时语法糖是 将 func = outter(func) ---> 简化成 ---> @outter
现在outter 就是 code(x) -----------------------------------------------> @code(x) 这就是有参的装饰器啦~,这里传X只是一个例子,其实可以传不限的参数。
三、如何使用装饰器
1.定义一个计算函数运行时间的装饰器
from functools import wraps
import time
def timmer(func):
@wraps(func)
def wrapper(*args,**kwargs): # 确保wrapper的参数,返回值,调用方式都跟func一模一样,但是可以增加一些功能
# 功能可以增加在这里
start = time.time
res = func(*args,**kwargs)
end = time.time
print(f‘执行函数用时start-end秒’)
return res
return wrapper
2.定义一个认证功能的装饰器
from functools import wraps
def auth(func):
@wraps(func)
def wrapper(*args,**kwargs): # 确保wrapper的参数,返回值,调用方式都跟func一模一样,但是可以增加一些功能
# 功能可以增加在这里
user_name = input('用户名>>>:‘)
psd = input('密码>>>:')
# 从文件查找用户名和密码认证
f = open('a.txt')
for line in f:
if user_name.split().lower() in line.lower and psd in line:
res = func(*args,**kwargs)
return res
else:
print('登录失败')
return wrapper
四、多层装饰器的套用
如果一个函数上面套用了很多个装饰器
@auth
@timmer
@...
def func():
pass
需要从内向外一层层使用装饰器功能,从函数开始,函数上面一层层剥开装饰器。