装饰器(二)
多层装饰器(语法糖)
当需要给一个函数添加多个功能时,应该给这个函数添加多个装饰器,而不是一个装饰器里添加多个功能。不过每一个装饰器的功能和装饰对象应该是什么关系需要我们掌握清楚。
# 基本结构
def func1(func_name1): # 装饰器1
print('加载1')
def inner1(*args, **kwargs):
print('执行1')
res1 = func_name1(*args, **kwargs)
return res1
return inner1
def func2(func_name2): # 装饰器2
print('加载2')
def inner2(*args, **kwargs):
print('执行2')
res2 = func_name2(*args, **kwargs)
return res2
return inner2
def func3(func_name3): # 装饰器3
print('加载3')
def inner3(*args, **kwargs):
print('执行3')
res3 = func_name3(*args, **kwargs)
return res3
return inner3
@func1
@func2
@func3
def func():
print('from func')
func()
# 执行结果
'''
加载3
加载2
加载1
执行1
执行2
执行3
from func
'''
注:需要注意,语法糖会将最近的被装饰函数名当做参数传入装饰器函数中。上述代码的运行顺序是先从内部向外加载装饰器,然后在从外部向内执行函数。
有参装饰器
无论是简易版本装饰器,还是完整版装饰器,都是在不需要传入外部参数时使用的。如果装饰器内部需要其他需求要用到其他参数时,我们就需要用到有参装饰器,目的就是给装饰器内部传递其他参数
# 基本结构
def func(index): # 向装饰器内部传参
def outer(func_name): # 向装饰器传函数名,不可更改
def inner(*args, **kwargs): # 闭包向函数传参,不可更改
# 执行函数前的操作(可能需要index的部分)
res = func_name(*args, **kwargs) # 接收返回值
# 执行函数后的操作(可能需要index的部分)
return res
return inner
return outer
@func('index')
def name():
print('输出名字')
name()
# 示例:
def func(choice): # 传装饰器内部一个choice参数
def outer(func_name): # 装饰器传入函数名
def inner(*args, **kwargs): # 闭包向函数内传参
if choice == 'y':
print('执行')
res = func_name(*args, **kwargs) # 接收函数执行后的返回值
return res
elif choice == 'n':
print('不执行')
else:
print('你他喵的')
return inner
return outer
@func('y')
def pr():
print('nice done,bro!!')
@func('n')
def nr():
print('sorry!!')
@func('t')
def tr():
print('选错了!!')
pr()
nr()
tr()
# 执行结果
'''
执行
nice done,bro!!
不执行
你他喵的
'''
注:
1.有参装饰器的语法糖需要加参数,所以语法糖就变成了@func(参数),左半部分@func是语法糖,右半部分func(参数)是函数名加括号(内有参数)结构。此时的情况下会先执行函数调用,然后返回值是函数名outer,然后会执行@outer语法糖。
2.如果装饰器由需要,有参装饰器可以向装饰器传多个参数。
函数装饰器结束

浙公网安备 33010602011771号