一、什么是装饰器?
装饰器本质上就是一个 python 函数,它可以让其他函数在不需要做出任何代码变动的前提下,额外增加功能,装饰器的返回值也是一个函数对象。
应用场景:插入日志,性能测试,事务处理,缓存等场景。
二、装饰器的形成过程。
我有一需求,我想让你测试这个函数的执行时间,在不改变这个代码的情况下:

def login(): print('游戏开始') import time # 导入时间模块 start_time = time.time() # 记录开始时间 login() # 开始函数 end_time = time.time() # 记录终止时间 print('此函数所用时间为%s' % (end_time - start_time)) 游戏开始 此函数所用时间为0.0

import time # 导入时间模块 def login(): time.sleep(0.3) # 停顿时间0.3 print('游戏开始') def timmer(): start_time = time.time() # 记录开始时间 login() # 开始函数 end_time = time.time() # 记录终止时间 print('此函数所用时间为%s' % (end_time - start_time)) timmer()
但是,如果有多个函数,我都想让你进行测试他们的执行时间,这 1.0 版是不是都得做出改变呢?

import time # 导入时间模块 def login(): # 第一函数 time.sleep(0.3) # 停顿时间0.3 print('游戏开始') def dier(): # 第二函数 time.sleep(0.4) print('准备好了么') def timmer(f): start_time = time.time() # 记录开始时间 f() # 开始函数 end_time = time.time() # 记录终止时间 print('此函数所用时间为%s' % (end_time - start_time)) timmer(login) timmer(dier) # 改变了我原来执行函数的执行方式

import time # 导入时间模块 def login(): # 第一函数 time.sleep(0.3) # 停顿时间0.3 print('游戏开始') def timmer(f): start_time = time.time() # 记录开始时间 f() # 开始函数 end_time = time.time() # 记录终止时间 print('此函数所用时间为%s' % (end_time - start_time)) f1 = login # 设变量 f1 将login 赋值给 f1 login = timmer # 【新设】变量 login 将 timmer 赋值给 login login(f1) # timmer(login)

import time # 导入时间模块 def login(): # 第一函数 time.sleep(0.3) # 停顿时间0.3 print('游戏开始') def timmer(f): def inner(): start_time = time.time() # 记录开始时间 f() # 开始函数 login end_time = time.time() # 记录终止时间 print('此函数所用时间为%s' % (end_time - start_time)) return inner login = timmer(login) # login = inner login() # 执行函数 inner()
在python中有个更简单的方法:语法糖: F1 = X1(F1)——> @X1

import time # 导入时间模块 def timmer(f): def inner(): start_time = time.time() # 记录开始时间 f() # 开始函数 login end_time = time.time() # 记录终止时间 print('此函数所用时间为%s' % (end_time - start_time)) return inner @timmer # login = timmer(login) def login(): # 第一函数 time.sleep(0.3) # 停顿时间0.3 print('游戏开始') login() # 执行函数 inner()
刚刚我们讨论的装饰器都是装饰不带参数的函数,现在要装饰一个带参数的函数怎么办呢?

def func(x,y): # func (x,y)实质上是 x = 5,y = 9 print(x,y) # 打印 x = 5, y = 9 func(y = 9, x = 5)

import time # 导入时间模块 def timmer(f): def inner(x,y): start_time = time.time() # 记录开始时间 f(x,y) # 开始函数 login(a,b) end_time = time.time() # 记录终止时间 print('此函数所用时间为%s' % (end_time - start_time)) return inner @timmer # login = timmer(login) def login(a,b): # 第一函数 print(a,b) # 打印参数 time.sleep(0.3) # 停顿时间0.3 print('游戏开始') login(8,9) # 执行函数 inner(x,y)

import time # 导入时间模块 def timmer(f): def inner(*args,**kwargs): start_time = time.time() # 记录开始时间 f(*args,**kwargs) # 开始函数 login(a,b) end_time = time.time() # 记录终止时间 print('此函数所用时间为%s' % (end_time - start_time)) return inner @timmer # login = timmer(login) def login(*args,**kwargs): # 第一函数 print(args,kwargs) # 打印参数 time.sleep(0) # 停顿时间0.3 print('游戏开始') @timmer def dier(*args,**kwargs): # 第二函数 print(args, kwargs) time.sleep(0.4) print('准备好了么') login(99,88,77,66,55) # 执行函数 inner(x,y) dier(999,520,0,126) # 为什么,我输给login 的数值能准确无误的送到 login 呢 这涉及到 * 的打散和重聚
我想让函数带返回值

import time # 导入时间模块 def timmer(f): def inner(*args,**kwargs): start_time = time.time() # 记录开始时间 ret = f(*args,**kwargs) # 开始函数 login(a,b) 将返回值666赋值给 ret end_time = time.time() # 记录终止时间 print('此函数所用时间为%s' % (end_time - start_time)) return ret # 将返回值666 返回给 inner(*args,**kwargs) return inner @timmer # login = timmer(login) def login(*args,**kwargs): # 第一函数 print(args,kwargs) # 打印参数 time.sleep(0) # 停顿时间0.3 print('游戏开始') return 666 # 返回值666 ,返回给 f(*args,**kwargs) @timmer def dier(*args,**kwargs): # 第二函数 print(args, kwargs) time.sleep(0.4) print('准备好了么') print(login(99,88,77,66,55)) # 执行函数 inner(x,y) 打印 login(99,88,77,66,55) 得到返回值 dier(999,520,0,126)