按照 Python 的编程原则,当一个函数被定义后,如要修改或扩展其功能应尽量避免直接修改函数定义的代码段,否则该函数在其他地方被调用时将无法正常运行。因此,当需要修改或扩展已被定义的函数的功能而不希望直接修改其代码时,可以使用装饰器。
先来看一个简单的例子:
def func1(function):
print("这里是执行function()函数之前")
def wrapper():
function()
wrapper()
print ("这里是执行function ()函数之后")
@func1
def func2():
print ("正在执行 function ()函数")
上述代码的运行结果如下所示:
>>> def func1(function):
... print("这里是执行function()函数之前")
... def wrapper():
... function()
... wrapper()
... print ("这里是执行function()函数之后")
>>> @func1
def func2():
. print ("正在执行 function ()函数")
这里是执行function()函数之前
正在执行 function()函数
这里是执行function()函数之后
这里
@func1
等效于
func1(func2)
在 Python 中一切皆是对象,所以装饰器本质上是一个返回函数的高阶函数。结合之前介绍的关键字参数,可以将一个函数作为其外部函数的返回值,例如:
def func1(arg = True):
def func2():
print("This is func2() function")
def func3():
print("This is func3() function")
if arg == True:
return func2
else :
return func3
func1()()
上述代码的运行结果如下所示。
>>> def func1(arg = True):
... def func2():
... print("This is func2() function")
... def func3():
... print("This is func3() function")
... if arg == True:
... return func2
... else :
... return func3
>>> func1()()
This is func2() function
可以看到,调用 func1( ) 时实际上运行了 func2( ) 函数,第二对括号是用以运行 func2( ) 函数的,如果不写这对括号,将只会得到 func2( ) 函数的引用信息,如图下所示。
>>> def func1(arg = True):
... def func2():
... print("This is func2() function")
... def func3():
... print("This is func3() function")
... if arg == True:
... return func2
... else :
... return func3
>>> func1()
.func2 at 0x0000014ED8D663A0>
装饰器也支持嵌套,嵌套的装饰器的执行顺序是从里向外,最先调用最里层的装饰器,最后调用最外层的装饰器,例如:
@a
@b
@c
def f()
pass
将按照以下顺序执行:
f = a(b(c(f)))