目录:
1.装饰器的标准格式,及使用方法
2.带参数的装饰器
3.多个装饰器装饰同一个函数
1.装饰器的标准格式,及使用方法
我们在使用函数的过程中,有时在定义好一个函数之后,还想增加一些新的功能,在不改变原函数的情况下,可在原函数的前后增加新的代码。
方法:在定义函数过程中,再定义一个新的函数,通过传参的方法进行嵌套实现功能。
基本语法如下:
def wrapper(func()):
def inner():
func() #要装饰的函数
return inner
- 1
- 2
- 3
- 4
调用时,利用语法糖@wrapper,在靠近要装饰的函数位置,例如
@wrapper
def test1():
print("test")
- 1
- 2
- 3
如果需要传参,按照下面的语法格式。
def wrapper(func):
def inner(*args,**kwargs):
#添加函数调用前代码
ret=func(*args,**kwargs)
#添加函数调用后代码
return ret
return inner
- 1
- 2
- 3
- 4
- 5
- 6
- 7
2.带参数的装饰器
假设这样一种应用:我们对多个函数同时使用装饰器,如果因为某种原因,需要暂时取消装饰器,如果函数不多,可以直接注释掉就可以了,但如果很多,就非常的麻烦,这时就可以引入带参数的装饰器,初始参数赋值True,通过修改初始参数,使得装饰器功能失效即可。
实际我们在调用装饰器的时候,上面的代码利用语法糖(@wrapper)是不能对装饰器传参的,所以还要再定义一层函数来实现,方法如下:
fagle=True
def wrapper_outer(fagle):
def wrapper(func):
def inner(*args,**kwargs):
if fagle:
# 添加函数调用前代码
ret=func(*args,**kwargs)
# 添加函数调用后代码
return ret
else:
ret = func(*args, **kwargs)
return ret
return inner
return wrapper
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
实际调用时,语法糖改为@wrapper_outer(fagle)即可
3.多个装饰器装饰同一个函数
当多个装饰器同时装饰一个函数时,会按照嵌套的方式运行,比如下面的代码
def wrapper1(func):
def inne1r(*args, **kwargs):
print("装饰器1前代码")
ret = func(*args, **kwargs)
print("装饰器1后代码")
return ret
return inner1
def wrapper2(func):
def inner2(*args, **kwargs):
print("装饰器2前代码")
ret = func(*args, **kwargs)
print("装饰器2后代码")
return ret
return inner2
@wrapper2
@wrapper1
def test():
print("test")
test()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
定义wrapper1和wrapper2 两个装饰器,同时装饰test1时,会按照下面的结果进行嵌套输入,结果如下:
装饰器2前代码
装饰器1前代码
test
装饰器1后代码
装饰器2后代码
举个例子,就类似俄罗斯套娃一样,一层层嵌套执行,比较难理解是参数的传递,可以参考下面代码的注释理解。
def wrapper1(func): # 2.调用函数,传参func=test
def inner1(*args, **kwargs): #13.执行inner1()
print("装饰器1前代码") #14.打印第二行代码
ret = func(*args, **kwargs) #15.执行func()等效于执行test(),上面第二步已经传参
print("装饰器1后代码") #17.执行完func(),打印第三行代码,inner1执行完成
return ret
return inner1 #3.返回inner的内存地址,
def wrapper2(func): #=inner1传参
def inner2(*args, **kwargs): #10.执行inner2
print("装饰器2前代码") # 11.打印第一行代码
ret = func(*args, **kwargs) #12.执行func()等效于执行inner1() ,因为上面第六步已经为func传参为inner1
print("装饰器2后代码") #18.inner1执行完成,继续执行inner2,打印第五行,执行完成
return ret
return inner2 # 7. 返回inner2
@wrapper2 # 8.等效于 test=wrapper2(test) 调用wrapper2后,返回inner2,test=wrapper2(test)=inner2
@wrapper1 # 1.最靠近函数,先执行,等效于 test=wrapper1(test) 4调用warpper1后返回inner,test=inner1
def test():
print("test") #16.执行第三行打印
test() #9.此时执行test()等效于执行inner2()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
前后来回调用比较绕,仔细看下还是能看懂的,实在看不懂,记住结果就好了