一、什么是装饰器
器是工具,这里指的是函数
装饰指的是添加额外的东西
所有装饰器的意思就是给定义好的函数添加上额外的功能
二、为什么要用装饰器
装饰器的目的是在不修改源代码以及调用方式的前提下为装饰对象添加新的功能
三、装饰器的原则
开放封闭式原则
开放指的是扩展功能是开放的
封闭指的是对源代码修改是封闭的
四、怎么使用装饰器
1.例题:先设定一个基本函数
def index(x,y): time.sleep(3) print('index %s %s' %(x,y))
2.在函数的基础上添加运算计时的功能
import time def index(x,y): start=time.time() time.sleep(3) #设定睡眠时间为三秒 print('index %s %s' %(x,y)) stop = time.time() print(stop - start) index(111,222)
3.上诉更改以满足功能的添加,现要求再基础函数不变的情况下添加
import time
def index(x,y):
time.sleep(3)
print('index %s %s' %(x,y))
def wrapper(): #新建一个函数, start=time.time() index(111,222) #执行上一个函数的条件 stop=time.time() print(stop - start) wrapper()
4.以满足未改变函数源代码要求,但函数的调用的调用方式改变了
现在进行优化第一步,将数值变量进行转化成 *args以及**kwargs,使index函数可是灵活设置
import time def index(x,y,z): time.sleep(3) print('index %s %s %s' %(x,y,z)) def wrapper(*args,**kwargs): start=time.time() index(*args,**kwargs) # index(3333,z=5555,y=44444) # 通过将index的变量改成*args以及**kwargs,可以灵活调用index的变量值 stop=time.time() print(stop - start) wrapper(3333,4444,5555)wrapper(3333,z=5555,y=44444)
5.优化第二步,将装饰器给多个函数使用,因此在原装饰器前加上一个外函数,使他与另外两个函数相关联
import time def index(x,y,z): #装饰一 time.sleep(3) print('index %s %s %s' %(x,y,z)) def home(name): #装饰二 time.sleep(2) print('welcome %s to home page' %name) def outter(func): # func = index的内存地址 新增外函数outter(),使其他函数亦可以使用者个装饰器 def wrapper(*args,**kwargs): start=time.time() func(*args,**kwargs) # index的内存地址() stop=time.time() print(stop - start) return wrapper #由于新增了一个函数,需要将原函数的值设置成全局的值 index=outter(index) # index=wrapper的内存地址 home=outter(home) # home=wrapper的内存地址 #使新增的外包函数和两个变量产生联系,装饰器可以使用两个变量 home('egon') # home(name='egon')
6.优化第三步 偷梁换柱将装饰器做的所有函数都可以使用
import time def index(x,y,z): time.sleep(3) print('index %s %s %s' %(x,y,z)) def home(name): time.sleep(2) print('welcome %s to home page' %name) def outter(func): def wrapper(*args,**kwargs): start=time.time() res=func(*args,**kwargs) stop=time.time() print(stop - start) return res return wrapper # 偷梁换柱:home这个名字指向的wrapper函数的内存地址 home=outter(home) res=home('egon') # res=wrapper('egon') print('返回值--》',res) #大方向:如何在方案三的基础上不改变函数的调用方式
二、装饰器的通用模板
2.1、先制定装饰器,然后在函数前用@装饰器名,等于调用装饰器
装饰器 def timmer(func): def wrapper(*args,**kwargs): start=time.time() res=func(*args,**kwargs) stop=time.time() print(stop - start) return res return wrapper # # # 在被装饰对象正上方的单独一行写@装饰器名字 # @timmer # index=timmer(index) def index(x,y,z): time.sleep(3) print('index %s %s %s' %(x,y,z)) # @timmer # home=timmer(ome) def home(name): time.sleep(2) print('welcome %s to home page' %name) index(x=1,y=2,z=3) home('egon')
2.2、装饰器模板
总结无参装饰器模板 def outter(func): def wrapper(*args,**kwargs): # 1、调用原函数 # 2、为其增加新功能 res=func(*args,**kwargs) return res return wrapper
2.3、无参装饰器属性
from functools import wraps def outter(func): @wraps(func) def wrapper(*args, **kwargs): """这个是主页功能""" res = func(*args, **kwargs) # res=index(1,2) return res return wrapper @outter # index=outter(index) def index(x,y): """这个是主页功能""" print(x,y) print(index.__name__) #打印函数名字 print(index.__doc__) #help(index) 打印注释