爱博体育那么被修饰的函数名就变成了变量名;同样

 新闻资讯     |      2021-06-04 01:00

前面章节中,我们已经讲授了 Python 内置的 3 种函数装饰器,别离是 @staticmethod、@classmethod 和 @property,个中 staticmethod()、classmethod() 和 property() 都是 Python 的内置函数。

那么,函数装饰器的事情道理是奈何的呢?假设用 funA() 函数装饰器去装饰 funB() 函数,爱博体育,如下所示: #funA 作为装饰器函数 def funA(fn): #... fn() # 执行传入的fn参数 #... return '...' @funA def funB(): #...
实际上,上面措施完全等价于下面的措施: def funA(fn): #... fn() # 执行传入的fn参数 #... return '...' def funB(): #... funB = funA(funB) 通过比对以上 2 段措施不难发明,利用函数装饰器 A() 去装饰另一个函数 B(),其底层执行了如下 2 步操纵:

将 B 作为参数传给 A() 函数;

将 A() 函数执行完成的返回值反馈回  B。


举个实例: #funA 作为装饰器函数 def funA(fn): print("C语言中文网") fn() # 执行传入的fn参数 print("") return "装饰器函数的返回值" @funA def funB(): print("进修 Python") 措施执行流程为:

C语言中文网
进修 Python

在此基本上,假如在措施末端添加如下语句: 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("") 措施执行功效为:

Python教程:


这里有须要给读者阐明一下这个措施,其实,它和如下措施是等价的: def funA(fn): # 界说一个嵌套函数 def say(arc): print("Python教程:",arc) return say def funB(arc): print("funB():", a) funB = funA(funB) funB("") 假如运行此措施会发明,它的输出功效和上面措施沟通。

显然,通过 funB() 函数被装饰器 funA() 修饰,funB 就被赋值为 say。这意味着,固然我们在措施显式挪用的是 funB() 函数,但其实执行的是装饰器嵌套的 say() 函数。

但尚有一个问题需要办理,即假如当前措施中,有多个(≥ 2)函数被同一个装饰器函数修饰,这些函数带有的参数个数并不相等,怎么办呢?

最简朴的办理方法是用 *args 和 **kwargs 作为装饰器内部嵌套函数的参数,*args 和 **kwargs 暗示接管任意数量和范例的参数。举个例子: 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("") other_funB("Python教程:","") 运行功效为:

C语言中文网:
Python教程:

函数装饰器可以嵌套 上面示例中,都是利用一个装饰器的环境,但实际上,Python 也支持多个装饰器,好比: @funA @funB @funC def fun(): #... 上面措施的执行顺序是里到外,所以它等效于下面这行代码:

fun = funA( funB ( funC (fun) ) )

这里不再给出详细实例,有乐趣的读者可自行编写措施举办测试。