JackLang 2020-01-11
函数装饰器的工作原理是怎样的呢?假设用 funA() 函数装饰器去装饰 funB() 函数,如下所示:
#funA 作为装饰器函数 def funA(fn): #... fn() # 执行传入的fn参数 #... return '...' @funA def funB(): #...
实际上,上面程序完全等价于下面的程序:
def funA(fn): #... fn() # 执行传入的fn参数 #... return '...' def funB(): #... funB = funA(funB)
#funA 作为装饰器函数 def funA(fn): print("C语言中文网") fn() # 执行传入的fn参数 print("http://c.biancheng.net") return "装饰器函数的返回值" @funA def funB(): print("学习 Python")
程序执行流程为: C语言中文网 学习 Python http://c.biancheng.net
在此基础上,如果在程序末尾添加如下语句:
print(funB)
其输出结果为:
装饰器函数的返回值
在分析 funA() 函数装饰器和 funB() 函数的关系时,细心的读者可能会发现一个问题,即当 funB() 函数无参数时,可以直接将 funB 作为 funA() 的参数传入。但是,如果被修饰的函数本身带有参数,那应该如何传值呢?
比较简单的解决方法就是在函数装饰器中嵌套一个函数,该函数带有的参数个数和被装饰器修饰的函数相同。例如:
def funA(fn): # 定义一个嵌套函数 def say(arc): print("Python教程:",arc) return say @funA def funB(arc): print("funB():", a) funB("http://c.biancheng.net/python") 程序执行结果为: Python教程: http://c.biancheng.net/python
这里有必要给读者分析一下这个程序,其实,它和如下程序是等价的:
def funA(fn): # 定义一个嵌套函数 def say(arc): print("Python教程:",arc) return say def funB(arc): print("funB():", a) funB = funA(funB) funB("http://c.biancheng.net/python")
如果运行此程序会发现,它的输出结果和上面程序相同。
def funA(fn): # 定义一个嵌套函数 def say(*args,**kwargs): fn(*args,**kwargs) return say @funA def funB(arc): print("C语言中文网:",arc) @funA def other_funB(name,arc): print(name,arc) funB("http://c.biancheng.net") other_funB("Python教程:","http://c.biancheng.net/python") 运行结果为: C语言中文网: http://c.biancheng.net Python教程: http://c.biancheng.net/python
上面示例中,都是使用一个装饰器的情况,但实际上,Python 也支持多个装饰器,比如:
@funA @funB @funC def fun(): #...
上面程序的执行顺序是里到外,所以它等效于下面这行代码:
fun = funA( funB ( funC (fun) ) )