装饰器的洋葱哲学:理解执行顺序与元编程
一、开篇:一次生产事故引发的思考
三年前,我在一个电商项目中遇到了一个诡异的 bug。系统日志显示某个关键 API 的函数名变成了 wrapper,导致监控系统无法正确追踪性能指标。更糟糕的是,这个函数被三个装饰器包裹,每次调用的执行顺序都让团队困惑不已。
那次事故让我深入研究了装饰器的本质,也让我意识到:装饰器不仅仅是语法糖,它是 Python 元编程的核心,理解它的执行顺序和元信息保留机制,是从中级开发者迈向高级工程师的必经之路。
今天,让我们一起剥开装饰器这颗'洋葱',看看它的每一层究竟隐藏着什么秘密。
二、装饰器的本质:函数是一等公民
2.1 最简单的装饰器
在深入复杂场景之前,让我们回到起点:
def simple_decorator(func):
"""最基础的装饰器"""
def wrapper(*args, **kwargs):
print(f"调用前:准备执行 {func.__name__}")
result = func(*args, **kwargs)
print(f"调用后:{func.__name__} 执行完毕")
return result
return wrapper
@simple_decorator
def greet(name):
"""向某人问候"""
return f"Hello, {name}!"
# 等价于:greet = simple_decorator(greet)
print(greet("Alice"))
输出:
调用前:准备执行 greet
调用后:greet 执行完毕
Hello, Alice!
2.2 装饰器的工作原理
装饰器的核心在于:
- 装饰器是一个接受函数作为参数的函数
- 它返回一个新的函数来替代原函数
@语法只是语法糖
# 手动演示装饰器的工作流程
def original_function():
():
():
wrapper
():
():
decorated_func_2 = my_decorator(decorated_func_2)
(decorated_func_1())
(decorated_func_2())


