最全面的Python装饰器教程了( 二 )


装饰器的应用场景:比如插入日志,性能测试,事务处理,缓存等等场景 。
import timedef timmer(f):def inner(): start_time = time.time()f()end_time = time.time()print('此函数的执行时间为{}'.format(end_time - start_time))return innerdef func1():print('in func1')time.sleep(1)func1 = timmer(func1)print(func1)func1()# 这里的func1是全新的func1,就是上面的赋值,此时相当于执行 inner函数输出结果:<function timmer.<locals>.inner at 0x03822DF8>in func1此函数的执行时间为1.0003533363342285代码从上至下执行
语法糖: 想测试谁,前面加@装饰器函数,即可 。写装饰器,约定俗成,函数名为wrapper
def wrapper(func): def inner(*args,**kwargs): '''被装饰函数之前''' ret = func(*args,**kwargs) '''被装饰函数之后''' return ret return inner@wrapperdef func(*args,**kwargs): print(args,kwargs) return 666print(func())输出结果:() {}666装饰器利用return制造了一个假象,func()执行,其实是执行inner() , func()把原来的func()给覆盖了
3.2 装饰器传参
例 1: 上面装饰器的例子,func1,要传2个参数a,b
【最全面的Python装饰器教程了】import timedef timmer(f): def inner(a,b): start_time = time.time() f(a,b) end_time = time.time() print('此函数的执行时间为{}'.format(end_time - start_time)) return inner@timmerdef func1(a,b): print('in func1 {}{}'.format(a,b)) time.sleep(1) # 模拟程序逻辑func1(1,2) 执行输出:in func1 12此函数的执行时间为1.0006024837493896例 2: 如果有多个参数呢?改成动态参数
import timedef timmer(f): def inner(*args,**kwargs): start_time = time.time() f(*args,**kwargs) end_time = time.time() print('此函数的执行时间为{}'.format(end_time - start_time)) return inner@timmerdef func1(*args,**kwargs): print('in func1 {}{}'.format(args,kwargs)) time.sleep(1) # 模拟程序逻辑func1(1,2,a='3',b=4) 执行输出:in func1 (1, 2){'b': 4, 'a': '3'}此函数的执行时间为1.000101089477539函数的执行时,*打散 ;
函数的定义时,*聚合 。
from functools import wrapsdef wrapper(f): # f = func1 def inner(*args,**kwargs):#聚合,args (1,2,3) '''执行函数之前的相关操作''' ret = f(*args,**kwargs)# 打散 1,2,3 '''执行函数之后的相关操作''' return ret return inner@wrapper # func1 = wrapper(func1) func1 = innerdef func1(*args):#args (1,2,3) 聚合 print(666) return argsprint(func1(*[1,2,3])) 执行输出:666(1, 2, 3)例 3 *****
import time #1.加载模块def timmer(*args,**kwargs): #2.加载变量 5.接收参数True,2,3 def wrapper(f): #6.加载变量 8.f = func1 print(args, kwargs) #9.接收timmer函数的值True,2,3 def inner(*args,**kwargs): #10.加载变量. 13.执行函数inner if flag: #14 flag = True start_time = time.time() #15 获取当前时间 ret = f(*args,**kwargs) #16 执行func1 time.sleep(0.3) #19 等待0.3秒 end_time = time.time() #20 获取当前时间 print('此函数的执行效率%f' % (end_time-start_time)) #21 打印差值 else: ret = f(*args, **kwargs) return ret #22 返回给函数调用者func1() return inner #11 返回给函数调用者wrapper return wrapper #7.返回给函数调用timmer(flag,2,3)flag = True #3 加载变量@timmer(flag,2,3) # 4.执行函数timmer(flag,2,3) 17.执行函数func1 两步:1,timmer(flag,2,3) 相当于执行wrapper 2.@wrapper 装饰器 func1 = wrapper(func1)def func1(*args,**kwargs): return 666 #18 返回给函数调用者f(*args,**kwargs)print(func1()) #12 执行函数 写装饰器,一般嵌套3层就可以了
3.3 多个装饰器,装饰一个函数
def wrapper1(func): # func == f函数名 def inner1(): print('wrapper1 ,before func') # 2 func() print('wrapper1 ,after func') # 4 return inner1def wrapper2(func): # func == inner1 def inner2(): print('wrapper2 ,before func') # 1 func() print('wrapper2 ,after func') # 5 return inner2@wrapper2 # f = wrapper2(f) 里面的f==inner1 外面的f == inner2@wrapper1 # f = wrapper1(f) 里面的f==函数名f 外面的f == inner1def f(): # 3 print('in f')f() # inner2() 执行输出:wrapper2 ,before funcwrapper1 ,before funcin fwrapper1 ,after funcwrapper2 ,after func哪个离函数近,哪个先计算  。 最底下的先执行
执行顺序如下图:

最全面的Python装饰器教程了

文章插图
 
多个装饰器,都是按照上图的顺序来的
4. 装饰器的 __name__ 和 __doc___
__name__:函数名
__doc___:函数的解释
普通函数
def func1(): """ 此函数是完成登陆的功能,参数分别是...作用 。return: 返回值是登陆成功与否(True,False) """ print(666)func1()print(func1.__name__) #获取函数名print(func1.__doc__) #获取函数名注释说明 执行输出:666func1此函数是完成登陆的功能,参数分别是...作用 。return: 返回值是登陆成功与否(True,False)


推荐阅读