python中带参数的装饰器的使用方法及应用场景
·
目录
在 Python 中,带参数的装饰器(decorator with arguments)本质上是三层函数结构。
原函数
f,装饰器函数g,装饰器外层函数h("INFO"),那么有h("INFO", g(f(X)))
一、为什么需要“带参数”的装饰器
普通装饰器:
def logger(func):
def wrapper(*args, **kwargs):
print("函数开始执行")
result = func(*args, **kwargs)
print("函数执行结束")
return result
return wrapper
使用:
@logger
def add(a, b):
return a + b
调用:
add(1,2)
输出:
函数开始执行
函数执行结束
但如果我们希望:
@logger(level="INFO")
控制日志等级,就需要带参数装饰器。
二、带参数装饰器标准结构
核心结构:三层函数
def decorator(arg1, arg2):
def real_decorator(func):
def wrapper(*args, **kwargs):
# 扩展逻辑
result = func(*args, **kwargs)
return result
return wrapper
return real_decorator
层级关系:
decorator(参数)
↓
real_decorator(func)
↓
wrapper(*args, **kwargs)
三、完整示例(最经典)
例子:带日志等级
def logger(level):
def decorator(func):
def wrapper(*args, **kwargs):
print(f"[{level}] 函数 {func.__name__} 开始执行")
result = func(*args, **kwargs)
print(f"[{level}] 函数 {func.__name__} 执行结束")
return result
return wrapper
return decorator
使用:
@logger("INFO")
def add(a, b):
return a + b
调用:
add(1,2)
输出:
[INFO] 函数 add 开始执行
[INFO] 函数 add 执行结束
四、执行流程(非常重要)
代码:
@logger("INFO")
def add(a, b):
return a + b
Python 实际执行:
第一步
执行:
logger("INFO")
返回:
decorator
第二步
执行:
decorator(add)
返回:
wrapper
此时:
add = wrapper
第三步
调用:
add(1,2)
实际上执行:
wrapper(1,2)
内部再调用:
func(1,2)
总结流程:
@logger("INFO")
等价于:
add = logger("INFO")(add)
非常重要!
五、带参数装饰器 + functools.wraps(推荐)
如果不加 wraps,函数信息会丢失:
add.__name__ = wrapper
正确写法:
from functools import wraps
def logger(level):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
print(f"[{level}] {func.__name__}")
return func(*args, **kwargs)
return wrapper
return decorator
这样:
add.__name__ == "add"
六、经典应用场景(非常重要)
1 日志控制
@log(level="DEBUG")
def train():
pass
常见于:
- 深度学习训练
- API 调用
- 服务日志
2 权限控制
Web开发中常见:
@require_role("admin")
def delete_user():
pass
实现:
def require_role(role):
def decorator(func):
def wrapper(user, *args, **kwargs):
if user.role != role:
raise PermissionError("权限不足")
return func(user, *args, **kwargs)
return wrapper
return decorator
3 重试机制(工程中非常常见)
例如网络请求:
@retry(times=3)
def request_api():
pass
实现:
def retry(times):
def decorator(func):
def wrapper(*args, **kwargs):
for i in range(times):
try:
return func(*args, **kwargs)
except Exception:
print(f"retry {i+1}")
return wrapper
return decorator
4 计时器(深度学习训练常用)
@timer(unit="ms")
def train_step():
pass
实现:
import time
def timer(unit="s"):
def decorator(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
t = end - start
if unit == "ms":
t *= 1000
print(f"time: {t:.3f}{unit}")
return result
return wrapper
return decorator
5 参数检查
@validate_type(int, int)
def add(a, b):
return a + b
七、进阶:带参数 + 类装饰器
有时也用 class decorator:
class Logger:
def __init__(self, level):
self.level = level
def __call__(self, func):
def wrapper(*args, **kwargs):
print(self.level)
return func(*args, **kwargs)
return wrapper
使用:
@Logger("INFO")
八、工程中最常见的写法总结
标准模板(建议记住):
from functools import wraps
def decorator(arg):
def real_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
# before
result = func(*args, **kwargs)
# after
return result
return wrapper
return real_decorator
九、一句话总结
带参数装饰器本质就是:
三层函数结构
参数层 → 装饰器层 → 包装函数层
结构:
decorator(args)
↓
decorator(func)
↓
wrapper()
更多推荐


所有评论(0)