语法
@文件名
def show(fn):
def temp(x,y):
print("===========")
z = fn(x,y)
return z
return temp
def myadd(a,b):
return a+b
def mysubstract(a,b):
return a-b
def mymulitply(a,b):
return a*b
def mydivide(a,b):
return a/b
add = show(myadd)
print(add(3,4))
substract = show(mysubstract)
print(substract(10,3))
优化使用@show 等价于 函数实际名=修饰器函数名(函数实际名)
def show(fn):
def temp(x,y):
print("===========")
return fn(x,y)
return temp
@show #myadd = show(myadd)
def myadd(a,b):
return a+b
@show
def mysubstract(a,b):
return a-b
@show
def mymulitply(a,b):
return a*b
@show
def mydivide(a,b):
return a/b
改进能适应不同格式的参数
在执行功能函数前把通用的功能或者要对函数参数进行的处理放到装饰器中去进行,常见的例如输出logging
def funx(*args,**kwargs): #args 收集关键字 #kwargs 收集关键字参数(字典等)
print(args,kwargs)
print(funx(1)) >>(1,)
print(funx(6,4,6,刘能=183283231123)) >>(6,4,6) {"刘能":"183283231123"}
def decorator(function):
def wrapper(*args,**kwargs):
print("=====开始======")
print(list(args)[0]) #元组转化为列表进行处理
x=function(*args,**kwargs)
return x
return wrapper
@decorator
def myadd(a,b,c):
return a+b+c
@decorator
def mysubstract(a,b,c):
return a-b-c
@decorator
def mymulitply(a,b):
return a*b
@decorator
def mydivide(a,b):
return a/b
print(myadd(3,4,3))
print(mysubstract(10,6,2))
print(mymulitply(10,6))
print(mydivide(10,2))
装饰器会修改原方法的name和doc,理论上我们不允许修改它,可以通过functools的wraps来实现
from functools import wraps
def log(flag):
def decorate(func):
@wraps(func)
def _wrap(*args,**kwargs):
try:
if flag:
func(*args,**kwargs)
print('name ',func.__name__)
except Exception as e:
print(e.args)
return _wrap
return decorate
@log(True)
def sum(a,b,c):
return a+b+c
x = sum(1,2,3)
print(sum) #打印sum的内存地址
print(sum.__name__) #打印sum的函数名
print(x)
有参装饰器
如何传入一个参数到装饰器中,装饰器中不允许直接传参数进入,所以我们一般采用的方法是在无参装饰器外在包裹一层函数,把参数传进去
from functools import wraps
def get_param(x):
def decorate(func):
@wraps(func)
def wrapper(*args,**kwargs):
if x =="a":
print('111111')
elif x = 'b':
print('222222222')
res = func(*args,**kwargs)
print('the func end')
return res
return wrappers
return decorate
@get_param('a') #decorate = get_param('a') @decorate
def func():
print('3333333333333')
>>>>
print('11111111')
print('3333333333')
print('the func end')
多个装饰器执行顺序
如果一个函数上有多个装饰器,其执行顺序是按照自下而上的顺序执行的,也就是最里面的先执行,再依次往上去执行,其内存调用类似于堆栈,先进后出,举例如下
def out1(function1):
def wrapper1(*args,**kwargs):
print("=====wrapper1 开始======")
x=function1(*args,**kwargs)
print("=====wrapper1 结束======")
return x
return wrapper1
def out2(function2):
def wrapper2(*args,**kwargs):
print("=====wrapper2 开始======")
x=function(*args,**kwargs)
print("=====wrapper2 结束======")
return x
return wrapper2
def out3(function3):
def wrapper3(*args,**kwargs):
print("=====wrapper3 开始======")
x=function3(*args,**kwargs)
print("=====wrapper3 结束======")
return x
return wrapper3
@out3 # func = out3(out2.wrapper2) return func = out3.wrapper3
@out2 # func = out2(out1.wrapper1) return func = out2.wrapper2
@out1 # func = out1(func) return func = out1.wrapper1
def func():
print('111111111')
func()
>>>>
#可以看到func被传递给了out3,即最后home指向了out3.wrapper3
#调用out3.wrapper3的function其实是out2.wrapper2
#调用out2.wrapper2的function其实是out1.wrapper1
print("=====wrapper3 开始======")
print("=====wrapper2 开始======")
print("=====wrapper1 开始======")
print('11111111111')
print("=====wrapper1 结束======")
print("=====wrapper2 结束======")
print("=====wrapper3 结束======")