Python 装饰器:从入门到实战的完整指南
装饰器(Decorator)是 Python中一种优雅的设计模式,它允许我们在不修改原函数代码的前提下,动态地添加功能。想象一下,你有一个已经写好的函数,现在需要为它添加日志记录、性能监控、权限验证等功能,但又不想改动函数本身的代码——这时候装饰器就派上用场了。
从技术层面讲,装饰器本质上是一个接收函数作为参数并返回新函数的高阶函数。让我们通过代码来逐步理解。
一、装饰器的基础语法
最基础的装饰器结构如下:
def my_decorator(func):
def wrapper(*args, **kwargs):
print("函数执行前")
result = func(*args, **kwargs)
print("函数执行后")
return result
return wrapper
@my_decorator
def say_hello(name):
print(f"Hello, {name}!")
say_hello("World")这里的 @my_decorator语法糖等价于 say_hello = my_decorator(say_hello)。关键在于理解 wrapper函数——它包裹了原始函数,可以在调用前后插入任意逻辑。
二、带参数的装饰器
实际应用中,我们经常需要给装饰器本身传递参数。这需要再增加一层函数嵌套:
def repeat(times):
"""重复执行函数的装饰器"""
def decorator(func):
def wrapper(*args, **kwargs):
for i in range(times):
print(f"第 {i 1}次执行:")
func(*args, **kwargs)
return wrapper
return decorator
@repeat(3)
def greet(message):
print(message)
greet("你好!")注意三层函数的关系:repeat接收装饰器参数,返回真正的装饰器 decorator,decorator接收被装饰函数,返回 wrapper。
三、实用案例:性能监控装饰器
让我们创建一个能测量函数执行时间的装饰器,这在性能优化中非常有用:
import time
from functools import wraps
def timing_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
start_time = time.perf_counter()
result = func(*args, **kwargs)
end_time = time.perf_counter()
elapsed = end_time - start_time
print(f"{func.__name__}执行耗时: {elapsed:.6f}秒")
return result
return wrapper这里使用了 functools.wraps,它是一个重要的细节——没有它,装饰后的函数会丢失原始的 __name__和 __doc__等信息。
四、实战:缓存装饰器
缓存是装饰器的经典应用场景。对于计算密集型且结果确定的函数,缓存可以大幅提升性能:
from functools import wraps
def memoize(func):
cache = {}
@wraps(func)
def wrapper(*args):
key = str(args)
if key not in cache:
cache[key] = func(*args)
return cache[key]
return wrapper五、类装饰器
装饰器不仅可以装饰函数,还可以装饰类。类装饰器接收一个类并返回一个新类。
六、装饰器栈
Python允许对同一个函数应用多个装饰器,它们会按照从下到上的顺序执行。
总结
装饰器是 Python中强大的元编程工具,掌握它可以让你写出更优雅、更可维护的代码。关键是要理解其本质——装饰器就是接收函数并返回新函数的高阶函数。
