📅  最后修改于: 2023-12-03 14:46:40.518000             🧑  作者: Mango
装饰器是Python中非常有用的功能,能够对函数进行增强。另外,Python还支持嵌套装饰器,也就是在一个装饰器函数里面又可以嵌套一个或多个装饰器函数。
首先,我们需要知道如何定义装饰器。以一个简单的例子来说明:
def my_decorator(func):
def wrapper():
print("Before the function is called.")
func()
print("After the function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
输出结果如下:
Before the function is called.
Hello!
After the function is called.
通过以上代码,我们可以发现,my_decorator
函数是一个装饰器函数,它将wrapper
函数作为返回值返回。在调用say_hello
函数时,Python自动调用了my_decorator
函数,并将say_hello
函数作为参数传递给了它。因此,say_hello
函数被传递给了wrapper
函数。
接下来,我们要介绍的是嵌套装饰器,即在my_decorator
函数内部再嵌套一个装饰器函数。代码如下:
def my_decorator(func):
def wrapper():
print("Before the function is called.")
func()
print("After the function is called.")
return wrapper
def my_decorator2(func):
def wrapper():
print("Before the function is called.")
func()
print("After the function is called.")
return wrapper
@my_decorator
@my_decorator2
def say_hello():
print("Hello!")
say_hello()
通过上述代码,可以看出,我们在my_decorator
函数内部嵌套了my_decorator2
函数。运行结果如下:
Before the function is called.
Before the function is called.
Hello!
After the function is called.
After the function is called.
可以看到,两个装饰器函数都对say_hello
函数进行了增强。他们的调用顺序是从上到下。先调用my_decorator2
函数,再调用my_decorator
函数。
嵌套装饰器可以应用于很多场景,下面简单列举几种:
假设我们有一个网站,需要对用户进行认证和授权,我们可以使用嵌套装饰器来实现这个功能。比如:
def require_login(func):
def wrapper():
if 'user' in session:
return func()
else:
return redirect('/login')
return wrapper
def require_admin(func):
def wrapper():
if 'role' in session and session['role'] == 'admin':
return func()
else:
abort(401)
return wrapper
@app.route('/dashboard')
@require_login
@require_admin
def dashboard():
# Some code here
require_login
和require_admin
都是装饰器函数。@require_login
表示对dashboard
函数进行require_login
装饰,@require_admin
则表示对dashboard
函数进行require_admin
装饰。
假设我们有一个需求,需要在每次运行某些函数时打印日志,可以使用嵌套装饰器来实现:
import logging
def logit(func):
@wraps(func)
def wrapper(*args, **kwargs):
logging.info('Running %s', func.__name__)
return func(*args, **kwargs)
return wrapper
@logit
def func1():
pass
@logit
def func2():
pass
在这个例子中,我们定义了一个logit
装饰器,使用了Python的logging
模块打印日志信息。@logit
表示对func1
和func2
函数进行logit
装饰。每次调用func1
和func2
函数时,都会自动打印日志信息。