装饰器
开放封闭原则
开放:对函数的扩展是开放的
封闭:对函数的修改是封闭的
装饰器的作用
在不更改原函数调用方式的前提下,对原函数添加新功能
# ①引子——为什么要有装饰器 为了在不修改原函数的基础上为函数添加新功能,产生了装饰器 # ②简单装饰器 def deco(f): def wrapper(): """原函数前添加的功能""" f() """原函数后添加的功能""" return wrapper def func(): print('这是原函数!') func = deco(func) func() # ③装饰器的语法糖 def deco(f): def wrapper(): """原函数前添加的功能""" f() """原函数后添加的功能""" return wrapper @deco # ——>此处效果等同于 func = deco(func) def func(): print('这是原函数') func() # ④带返回值的装饰器 def deco(f): def wrapper(): """原函数前添加的功能""" res = f() """原函数后添加的功能""" return res return wrapper @deco def func(): print('这是原函数') func() # ⑤带参数、带返回值的装饰器 def deco(f): def wrapper(*args,**kwargs): """原函数前添加的功能""" res = f(*args,**kwargs) """原函数后添加的功能""" return res return wrapper @deco def func(*args,**kwargs): print('这是原函数') func(*args,**kwargs) # ⑥多层装饰器 # todo # ⑦多个装饰器修饰同一个函数 # todo
装饰器的固定格式
def deco(f): def wrapper(*args,**kwargs): """原函数前添加的功能""" res = f(*args,**kwargs) """原函数后添加的功能""" return res return wrapper @deco def func(*args,**kwargs): pring('这是原函数') func(*args,**kwargs)
装饰器的固定格式—wraps版
如果想使用原函数的双下方法,则需要再调用系统装饰器@ wraps(func)
from functools import wraps def deco(func): @wraps(func) #加在最内层函数正上方 def wrapper(*args,**kwargs): return func(*args,**kwargs) return wrapper @deco def origin_func(): ''' 这是原函数的注释 :return: ''' print('这是原函数') # 虽然已经执行了装饰器,origin_func已经指向wrapper,但是如果用了@wraps(func)装饰器之后调用origin_func的双下方法依然是原函数origin_func的 print(origin_func.__name__) >>> origin_func print(origin_func.__doc__) >>> 这是原函数的注释 >>> :return:
带参数的装饰器
def outer(flag): def timer(func): def inner(*args,**kwargs): if flag: print('''执行函数之前要做的''') re = func(*args,**kwargs) if flag: print('''执行函数之后要做的''') return re return inner return timer # 此处先执行函数调用outer(False) —> 返回timer —>@timer —>func = timer(func) —> func = inner @outer(False) def func(): print(111) func()
多个装饰器装饰同一个函数
def wrapper1(func): def inner1(): print('wrapper1 ,before func') func() print('wrapper1 ,after func') return inner1 def wrapper2(func): def inner2(): print('wrapper2 ,before func') func() print('wrapper2 ,after func') return inner2 @wrapper2 # 将inner1进行装饰,即inner1 = wrapper2(inner1) = inner2 @wrapper1 # 先执行这个装饰器,即f = wrapper1(f) = inner1 def f(): print('in f') f() # 结果 >>> wrapper2 ,before func >>> wrapper1 ,before func >>> in f >>> wrapper1 ,after func >>> wrapper2 ,after func