Python装饰器本质是接收函数并返回新函数的高阶函数,通过闭包包装原函数、保留元信息(如用@wraps),实现行为增强而不改原代码。

Python装饰器本质是“函数的函数”——它接收一个函数作为参数,返回一个新的函数(或可调用对象),在不修改原函数代码的前提下,动态增强其行为。核心不在语法糖 @decorator,而在“包装+替换”这一动作:把原函数包进新逻辑里,再让变量名指向这个增强后的可调用体。
装饰器不是魔法,是显式函数调用的语法糖
写 @log_time 看似神秘,实际等价于:
def func(): ...
func = log_time(func)
也就是说,装饰器语句会在函数定义后立即执行,把 func 替换为 log_time(func) 的返回值。理解这点,就拆掉了第一层迷雾。
立即学习“Python免费学习笔记(深入)”;
关键结构:闭包封装原函数 + 内部函数控制执行流
一个典型装饰器长这样:
def timer(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
print(f"{func.__name__} took {time.time()-start:.2f}s")
return result
return wrapper
这里三个要点必须清楚:
-
外层函数接收被装饰函数(
func),并保持对其的引用 -
内层函数(
wrapper)保存原函数和增强逻辑,形成闭包 - 返回内层函数本身(不加括号),确保后续调用触发的是包装后的行为
带参数的装饰器:多套一层函数即可
当你看到 @retry(times=3),这不是直接装饰,而是“装饰器工厂”:
def retry(times=1):
def decorator(func):
def wrapper(*args, **kwargs):
for i in range(times):
try:
return func(*args, **kwargs)
except Exception:
if i == times - 1: raise
return wrapper
return decorator
调用顺序是:retry(times=3) → 返回 decorator → decorator(func) → 返回 wrapper。三层嵌套,各司其职。
别忘了保留原函数的“身份信息”
直接装饰后,func.__name__ 变成 'wrapper',help(func) 显示的是 wrapper 的文档。解决方法很简单:
用 from functools import wraps,并在 wrapper 上加 @wraps(func):
@wraps(func)
def wrapper(*args, **kwargs): ...
它会自动复制 func.__name__、__doc__、__module__ 等属性到 wrapper 上,避免调试和反射时“找不到人”。
不复杂但容易忽略。抓住“传函数、返函数、包逻辑、留元信息”这十六个字,装饰器就从炫技变成了顺手工具。










