函数装饰器原理演示:
# funnA作为函数装饰器
def funA(fn):
# ...
fn() # 执行传入的fn参数
# ...
return "..."
@funA
def funB():
# ...
以上程序完全等价于:
def funA(fn):
# ...
fn() # 执行传入的fn参数
# ...
return "..."
def funB():
# ...
B= funA(funB)
通过以上两段程序发现,通过函数funA去装饰函数funB,执行了两个步骤:
1、将函数funB作为参数传给funA
2、将函数funA执行完成的返回值反馈给funB,通过打印函数输出
实例:
# funnA作为函数装饰器
def funA(fn):
print("helloA")
fn() # 执行传入的fn参数
return "装饰器返回的结果"
@funA
def funB():
print("helloB")
输出:
helloA
helloB
添加如下代码:
print(funB)
输出:装饰器返回的结果
被装饰的函数不再是原来的函数,这取决于装饰器返回的值,如果装饰器返回的是普通变量,那么被装饰的函数名就成为变量名,可以通过打印函数名获得装饰器返回值;如果装饰器返回的是一个函数名称,那么被装饰的函数依然是一个函数
带参数的函数装饰器:
如果被装饰的函数有参数时,该怎么作为值传给装饰器
# 比较简单的方法就是装饰器中嵌套一个函数,该函数带的参数的个数和被装饰的函数相同
def funA(fn):
# 定义一个嵌套函数
def say(name):
print("名字叫:",name)
return say
@funA
def funB(name):
print("funB")
funB("张三")
# 通过装饰器funB被赋值为say,虽然是显式的调用funB函数,但实际是执行say()函数
如果有多个函数被不同装饰器修饰,而这些函数的参数个数又不想等,那么可以用*args 和 **kwargs 作为装饰器内部嵌套函数的参数
def funA(fn):
def say(*args,**kwargs):
# 执行被装饰的函数
fn(*args,**kwargs)
return say
@funA
def funB(name):
print("我的名字:",name)
@funA
def funC(name,age):
print("你的名字和年龄:",name,age)
funB("张三")
funC("李四",22)
装饰器可以嵌套:
@funA
@funB
@funC
def fun():
#...
# 上面程序的执行顺序是里到外,所以它等效于下面这行代码:
fun = funA( funB ( funC (fun) ) )