装饰器本质是接收函数为参数并返回新函数的高阶函数,如@log等价于func = log(func);手写时需用闭包,外层传func、内层wrapper处理逻辑;@语法仅为语法糖,多装饰器从下往上嵌套,带参装饰器需三层嵌套。

装饰器本质是“函数的函数”
装饰器不是语法糖的魔法,它就是一个接收函数作为参数、返回新函数的普通函数。比如 @log 看似写在函数上方,实际等价于 func = log(func)。关键点在于:被装饰函数名指向了装饰器返回的新函数,原函数逻辑被包裹其中,执行时机由新函数控制。
手写一个最简装饰器
先忽略 @ 语法,从基础开始:
- 定义一个闭包:外层函数接收原函数
func,内层函数wrapper接收任意参数(*args, **kwargs),调用前/后插入逻辑,最后返回func(*args, **kwargs) - 外层函数返回
wrapper(注意不是wrapper()) - 手动应用:把原函数传进去,再用新名字调用
示例:
def my_decorator(func):
def wrapper(*args, **kwargs):
print("调用前")
result = func(*args, **kwargs)
print("调用后")
return result
return wrapper
<p>def hello():
print("Hello")</p><p>hello = my_decorator(hello) # 手动装饰
hello() # 输出:调用前 → Hello → 调用后</p>@语法只是语法糖,底层仍是函数调用
@my_decorator 放在函数定义前,Python 在加载该函数时自动执行 hello = my_decorator(hello)。它不改变原函数定义,只改写其绑定的名称。多个装饰器如 @a @b @c 等价于 c = a(b(c)),顺序是从下往上套用。
立即学习“Python免费学习笔记(深入)”;
带参数的装饰器需要再套一层
如果想让装饰器接收配置(比如 @retry(times=3)),必须多封装一层:
- 最外层函数接收装饰器参数(如
times) - 中间层接收原函数
func - 最内层
wrapper执行逻辑并调用原函数 - 返回关系是:最外层 → 中层 → 内层
这样 @retry(times=3) 实际触发的是最外层函数调用,返回中层函数,再用于装饰目标函数。










