装饰器和它绑定的函数通常是一对一的关系,但它不仅限于这种关系。装饰器的核心作用是增强或修改函数的行为。装饰器是一种高阶函数,它们的本质是接收一个函数作为输入,并返回一个新的函数。
例如,在 Flask 中:
@app.route('/')
def hello():
return 'Hello, World!'
这里的装饰器 @app.route('/')
绑定了 hello()
函数。在访问 '/'
路径时,hello()
函数会被调用,同时 @app.route()
的逻辑也会起作用。这个过程中,它们表现为“一对一”关系:访问指定路径时,执行特定的函数。
有时,一个装饰器可以同时绑定多个路径(或条件)来处理不同的 URL。例如:
@app.route('/')
@app.route('/index')
def hello():
return 'Hello, World!'
在这个例子中,@app.route('/')
和 @app.route('/index')
都绑定了同一个 hello()
函数。无论用户访问 '/'
还是 '/index'
,都会调用同一个函数 hello()
,这就是装饰器的“一对多”关系。
装饰器的标准结构如下:
def my_decorator(func):
def wrapper():
# 这里可以添加一些在原函数执行之前的操作
result = func() # 调用被装饰的函数
# 这里可以添加一些在原函数执行之后的操作
return result
return wrapper
在这个结构中:
wrapper()
是包裹函数,它包含了对func()
(被装饰函数)的调用。- 通过在
func()
前后插入逻辑,wrapper()
就可以在调用原函数前后做一些额外的事情,比如打印日志、验证权限、计时等。 - 装饰器最后返回
wrapper
函数,而不是直接返回原始的func()
,所以当我们调用被装饰的函数时,实际上调用的是wrapper()
,这就允许我们灵活控制函数的执行过程。
一个常见的用法是在 wrapper()
中使用 *args
和 **kwargs
来处理带有参数的函数。
def log_decorator(func):
def wrapper(*args, **kwargs):
print("Function is about to run...")
result = func(*args, **kwargs) # 传递参数
print("Function has finished running.")
return result
return wrapper
@log_decorator
def greet(name):
print(f"Hello, {name}!")
greet("Alice")
输出:
Function is about to run...
Hello, Alice!
Function has finished running.
在这个例子中,wrapper(*args, **kwargs)
能够接受任何参数并传递给 func
,这样装饰器可以装饰各种带参数的函数。