装饰器是Python的一个重要特性,它允许我们在不修改原始函数代码的情况下,增加函数的功能。装饰器本质上是一个函数,它接受一个函数作为参数,并返回一个新的函数。这个新的函数通常会包含原始函数的一些额外功能。
让我们从个简单的例子开始。假设我们有一个函数,它打印一条消息:
def hello():
print("Hello, world!")
我们可以创建一个装饰器,它在调用hello
函数之前和之后打印一些额外的信息:
def print_info(func):
def wrapper():
print("Before call")
func()
print("After call")
return wrapper
hello = print_info(hello)
现在,当我们调用hello
函数时,它会首先打印"Before call",然后执行原始的hello
函数,最后打印"After call"。
装饰器还可以接受参数。例如,我们可以创建一个装饰器,它接受一个参数,并在调用被装饰的函数之前和之后打印这个参数:
def print_info(message):
def decorator(func):
def wrapper():
print(message)
func()
print(message)
return wrapper
return decorator
@print_info("Extra info")
def hello():
print("Hello, world!")
在这个例子中,我们使用了@
语法,这是Python的一种语法糖,它等价于hello = print_info("Extra info")(hello)
。
注意装饰器的顺序很重要。如果我们有多个装饰器,它们会按照从下到上的顺序应用。这意味着最接近原始函数的装饰器最先被应用,最远离原始函数的装饰器最后被应用。
最后,让我们看一个实际的例子。假设我们正在开发一个web应用,我们想要记录每个请求的处理时间。我们可以创建一个装饰器来完成这个任务:
import time
def timing_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} took {end_time - start_time} seconds to run")
return result
return wrapper
@timing_decorator
def handle_request(request):
# 处理请求...
pass
在这个例子中,每次我们调用handle_request
函数时,都会自动打印出它的运行时间。这就是装饰器的强大之处:它们允许我们在不修改原始函数代码的情况下,增加函数的功能。