一:什么是装饰器
器:指的是工具,可以定义为函数
装饰:指的是为其他事物添加额外的东西点缀
装饰器:指的是定义一个函数,该函数是用来给其他函数添加额外的功能
二、为什么要用装饰器
开放封闭原则:
开放:指的是对拓展功能是开放的
封闭:指的是对修改源代码是封闭的
对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。对修改封闭,意味着对象一旦设计完成,就可以独立完成其工作,而不要对其进行修改。
装饰器就是在不修改被装饰对象源代码以及调用方式的前提下为被装饰对象添加新功能。
三、装饰器的实现
函数装饰器分为:无参装饰器和有参装饰两种,二者的实现原理一样,都是’函数嵌套+闭包+函数对象’的组合使用的产物。
3.1:无参装饰器的实现
无参装饰器的模版
def outer(func):
def wrapper():
res = func()
return res
return wrapper
@outer # 加在被装饰对象的上方
如果想为下述函数添加统计其执行时间的功能
import time
def get_time():
time.sleep(3)
print("welcome")
return 200
get_time()
使用装饰器:
import time
def outer(func):
def wrapper():
stat_time = time.time()
res = func()
end_time = time.time()
print(f'程序运行的时间为{end_time-stat_time}')
return res
return wrapper
@outer
def get_time():
time.sleep(3)
print("welcome")
return 200
get_time()
输出结果:
welcome
程序运行的时间为3.0009207725524902
3.2:有参装饰器的实现
有参装饰器的模版
def outer(func):
def wrapper(*args, **kwargs):
res = func(*args, **kwargs)
return res
return wrapper
@outer # 加在被装饰对象的上方
如果想为下述函数添加统计其执行时间的功能
import time
def time_demo(a, b):
time.sleep(3)
print("welcome")
print(a+b)
time_demo(3, 5)
使用装饰器:
import time
def outer(func):
def wrapper(a, b):
stat_time = time.time()
res = func(a, b)
end_time = time.time()
print(f'程序运行的时间为{end_time-stat_time}')
return res
return wrapper
@outer
def time_demo(a, b):
time.sleep(3)
print("welcome")
print(a+b)
time_demo(3, 5)
输出结果:
welcome
8
程序运行的时间为3.0009207725524902
3.3:装饰器函数本身带有参数
@logging(level='INFO')它就是一个函数,会被立刻执行,返回结果是一个装饰器。
与上面的例子相同:
import time
def loglevel(level):
def outer(func):
def wrapper(a, b):
stat_time = time.time()
res = func(a, b)
end_time = time.time()
print(f'程序运行的时间为{end_time-stat_time}')
if level == 'INFO':
print("level is INFO")
return res
return wrapper
return outer
@loglevel(level='INFO') # 相当于:time_demo=loglevel("INFO")(time_demo), -> loglevel("INFO") = outer, 因此time_demo=outer(time_demo)
def time_demo(a, b):
time.sleep(3)
print("welcome")
print(a+b)
time_demo(3, 5)
@loglevel(level='INFO'):先执行loglevel(level='INFO'),得到outer返回值后,再执行@outer
输出结果:
welcome
8
程序运行的时间为3.0051047801971436
level is INFO
3.4:叠加多个装饰器
@deco3
@deco2
@deco1
def index():
pass
执行顺序是:从最上面的装饰器依次往下执行,将下面的作为参数传入
index=deco3(deco2(deco1(index)))