带参数的装饰器本质是“装饰器工厂”,需三层嵌套:外层接收装饰器参数并返回中层函数,中层接收被装饰函数并返回内层函数,内层接收调用参数、执行逻辑并返回原函数结果;漏掉任一层return将导致TypeError或返回None。

带参数的装饰器本质是“装饰器工厂”,它先接收参数,再返回一个真正的装饰器函数。关键在于多一层函数嵌套:外层接收装饰器参数,中层接收被装饰函数,内层执行实际逻辑。
装饰器参数传递的三层结构
带参数装饰器必须有三层嵌套函数:
-
最外层:接收装饰器本身的参数(如
@log(level='INFO')里的level),返回中层函数 -
中层:接收被装饰的函数对象(
func),返回内层函数 -
内层:接收被装饰函数的调用参数(
*args, **kwargs),执行前置/后置逻辑,并调用原函数
一个实用的带参日志装饰器
下面是一个记录执行级别和函数名的日志装饰器:
def log(level='INFO'):
def decorator(func):
def wrapper(*args, **kwargs):
print(f'[{level}] Calling {func.__name__}')
result = func(*args, **kwargs)
print(f'[{level}] {func.__name__} finished')
return result
return wrapper
return decorator
<p>@log('DEBUG') # 传入装饰器参数 'DEBUG'
def greet(name):
return f'Hello, {name}!'</p><p>print(greet('Alice'))
登录后复制
输出为:
立即学习“Python免费学习笔记(深入)”;
[DEBUG] Calling greet [DEBUG] greet finished Hello, Alice!
登录后复制
为什么不能直接在中层接收装饰器参数?
因为 Python 解析@log('DEBUG')时,会立即调用log('DEBUG'),期望它返回一个可调用对象(即真正的装饰器)。如果log没有外层,它就只能接收func,无法拿到'DEBUG'——此时@log('DEBUG')等价于log('DEBUG')(func),而log('DEBUG')必须返回一个能接收func的函数。
版权声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。
还木有评论哦,快来抢沙发吧~