装饰器
通过使用闭包函数(嵌套函数),来达到不改变原方法,而对原方法添加功能的作用
1 import time 2 from functools import wraps 3 4 5 def timer(f): 6 @wraps(f) 7 def inner(*args,**kwargs): 8 start = time.time() 9 res = f(*args,**kwargs) 10 end = time.time() 11 print(end - start) 12 return res 13 return inner 14 15 16 @timer #func = timer(func(a)) 17 def func(a): 18 '''this is a function''' 19 return f'function:{a}' 20 21 res = func('f') 22 print(res) 23 print(func.__name__) 24 print(func.__doc__)
对func函数添加计算时间的功能,16行@语法,称之为语法糖,等同于 func = timer(func(a));
__name__ 和__doc__方法,可查看函数的方法和注释,由于使用了装饰器,故显示的都为装饰器中的属性,若要显示原来属性,则使用functools的wrap方法对装饰的函数进行装饰;
控制装饰器的执行
对装饰器函数在外包一层函数,使用布尔值进行判断调用
1 Flag = True 2 def outer(Flag): 3 def timer(f): 4 @wraps(f) 5 def inner(*args,**kwargs): 6 if Flag: 7 start = time.time() 8 res = f(*args,**kwargs) 9 end = time.time() 10 print(end - start) 11 else: 12 res = f(*args,**kwargs) 13 return res 14 return inner 15 return timer 16 17 @outer(Flag) 18 def func(a): 19 '''this is a function''' 20 return f'function:{a}' 21 22 res = func('hello') 23 print(res)
通过修改布尔值,就可调控该装饰器是否执行
多个装饰器
当有多个装饰器时,离函数最近的装饰器先执行
1 def wrapper1(func): 2 def inner(): 3 print('wrapper1 ,before func') 4 func() 5 print('wrapper1 ,after func') 6 return inner 7 8 def wrapper2(func): 9 def inner(): 10 print('wrapper2 ,before func') 11 func() 12 print('wrapper2 ,after func') 13 return inner 14 15 @wrapper2 16 @wrapper1 17 def f(): 18 print('in f') 19 20 f()
实际执行顺序为wrapper1,然后是wrapper2;在调用wrapper1时,返回的为wrapper1的inner函数,此时对该inner函数,进行wrapper2的装饰,故输出如下图。
该输出如,照镜子,f为镜子,我称之为镜子输出
talk is cheap show me the code