带参数装饰器本质是三层嵌套函数:外层接收配置参数并返回中间层,中间层接收被装饰函数并返回内层包装函数,内层执行逻辑并访问外层变量;必须用嵌套函数实现,漏掉中间层会导致报错;使用时需加括号如@log();需用@wraps保留原函数元数据。

带参数装饰器的本质是“三层函数”
普通装饰器接收一个函数作为参数,返回一个新的函数;而带参数的装饰器,其实是先被调用一次,传入配置参数,再返回一个“真正的装饰器”。这个过程涉及三个层级:
- 最外层:接收装饰器的参数(如 @log(level='INFO') 中的 level),返回第二层函数
- 中间层:接收被装饰的函数(func),返回最内层包装函数
- 最内层:实际执行逻辑的闭包函数,可访问外层所有变量(如 level 和 func)
写法模板与关键细节
必须用嵌套函数实现,不能省略任意一层。常见错误是漏掉中间层,导致语法报错或行为异常:
def log(level='INFO'):
def decorator(func): # ← 这一层不能少!它才是真正的装饰器
def wrapper(*args, **kwargs):
print(f'[{level}] Calling {func.__name__}')
return func(*args, **kwargs)
return wrapper
return decorator # ← 返回的是 decorator,不是 wrapper
使用时注意括号:带参数装饰器必须加括号,即使无参也要写 @log(),否则 Python 会把函数名当参数传进去,引发 TypeError。
为什么需要高阶函数支撑
装饰器本身就是高阶函数的典型应用——函数接收函数、返回函数。带参数装饰器进一步体现高阶特性:
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
- 函数作为返回值:外层函数返回 decorator,它本身又是接收函数的高阶函数
- 闭包保存状态:中间层和内层构成闭包,使 level 等参数在 wrapper 中持续可用
- 运行时动态定制:不同参数组合可生成不同行为的装饰器,比如 @retry(times=3) 和 @retry(times=5) 是两个独立的装饰逻辑
实用技巧:用 functools.wraps 保留原函数信息
不加处理时,被装饰函数的 __name__、__doc__ 会变成 wrapper 的,影响调试和文档提取。解决方法是在内层函数前加:
from functools import wraps
<p>def log(level='INFO'):
def decorator(func):
@wraps(func) # ← 关键一行
def wrapper(*args, *<em>kwargs):
print(f'[{level}] {func.<strong>name</strong>}')
return func(</em>args, **kwargs)
return wrapper
return decorator</p>
这样 wrapper 就会自动复制 func 的元数据,调用 help() 或反射时表现正常。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










