需求1:需要大长脸写一个功能,测试一下同事二狗的函数的执行效率
import time #引入time模块
print(time.time())
def func1(): time.sleep(1) print('来了,老弟') def func2(): time.sleep(1) print('回手 掏 ,走位走位....') # # import time start_time = time.time() func1() end_time = time.time() print('此函数的执行时间是%s' % (end_time-start_time)) import time start_time = time.time() func2() end_time = time.time() print('此函数的执行时间是%s' % (end_time-start_time)) # 第一版本不好,重复造轮子,测试函数的效率 必须得复制代码测试 改版:
# 第二版 将脸哥的代码封装到函数中,基本完成, import time def func1(): time.sleep(0.6) print('来了,老弟') def func2(): time.sleep(0.5) print('回手 掏 ,走位走位....') def timmer(f): start_time = time.time() f() end_time = time.time() print('此函数的执行时间是%s' % (end_time-start_time)) timmer(func1) timmer(func2)
# 第三版 领导要求在生产环境测试函数的真正的执行效率:线上500个函数 # 线上问题: # 线上的函数你不改变 # 函数的原本的调用方式不能改变 import time def func1(): time.sleep(0.6) print('来了,老弟') def func2(): time.sleep(0.5) print('回手 掏 ,走位走位....') # 原本线上的调用方式: # func1() # func2() # 但是用了脸哥的测试效率的函数之后 def timmer(f): start_time = time.time() f() end_time = time.time() print('此函数的执行时间是%s' % (end_time-start_time)) # 此时你已经改变了原函数的调用方式,并且程序执行了两遍 func1() timmer(func1)
# 第四版:第三版 没有改变函数里面的函数体,但是改变了函数的调用方法,所以要解决:用最少的代码,解决调用方式一致性的问题。 # 最终完成的需求 func1() 这个指令既要执行func1函数,又要测试效率 import time def func1(): time.sleep(0.6) print('来了,老弟') # # def func2(): # time.sleep(0.5) # print('回手 掏 ,走位走位....') def timmer(f): # f = func1 函数的内存地址 def inner(): start_time = time.time() f() end_time = time.time() print('此函数的执行时间是%s' % (end_time-start_time)) return inner func1 = timmer(func1) # = inner func1() # inner()
# 第五版: 最终基础版 python提供一个机制,优化,语法糖 @ 上面还是不够优化,我们引入第5种python语法糖@ 示例:func1 = timmer(func1) 就等于@timmer import time def timmer(f): # f = func1 函数的内存地址 def inner(): start_time = time.time() f() end_time = time.time() print('此函数的执行时间是%s' % (end_time - start_time)) return inner @timmer # func1 = timmer(func1) def func1(): time.sleep(0.6) print('来了,老弟') func1() # inner() @timmer def func2(): time.sleep(0.6) print('来le') func2() @timmer def func3(): time.sleep(0.6) print('来') func3()
二、被装饰函数带参数
import time def timmer(f): # f = func1或者func2 函数的内存地址 def inner(*args, **kwargs): start_time = time.time() f(*args, **kwargs) end_time = time.time() print('此函数的执行时间是%s' % (end_time - start_time)) return inner @timmer # func1 = timmer(func1) 在某个函数的上面加上这个 def func1(a): time.sleep(0.6) print('来了,%s' % (a)) func1('alex') @timmer # func2 = timmer(func2) def func2(c,d): time.sleep(0.6) print('%s 年龄 %s' % (c,d)) func2('二狗',21)
三、被装饰函数带返回值
import time def timmer(f): # f = func1 函数的内存地址 def inner(*args, **kwargs): start_time = time.time() ret = f(*args, **kwargs) end_time = time.time() print('此函数的执行时间是%s' % (end_time - start_time)) return ret return inner @timmer # func1 = timmer(func1) def func1(a): time.sleep(0.6) print('来了,%s' % (a)) return 666 print(func1('alex')) # print(inner('alex'))
总结:
1、装饰器本质其实闭包,
2、装饰器在不改变原函数的内部函数体以及调用方式的前提下,给函数增加了额外的功能:登录,注册,打印日志,函数效率等等。
四、手写装饰器
# 手写装饰器1,先写闭包: def wrapper(f): def inner(): f() return inner # 手写装饰器2,增加参数: def wrapper(f): def inner(*args,**kwargs): f(*args,**kwargs) return inner # 手写装饰器3,增加返回值ret,增加函数部分:
def wrapper(f): def inner(*args, **kwargs): ''' 执行被装饰的函数之前的操作''' print('执行之前', 555) #示例 ret = f(*args, **kwargs) print('执行之后', 666) #示例 ''' 执行被装饰的函数之后的操作''' return ret return inner @wrapper def func1(): pass func1()