python中带参数的装饰器的使用方法及应用场景
目录
- 一、为什么需要“带参数”的装饰器
- 二、带参数装饰器标准结构
- 三、完整示例(最经典)
- 例子:带日志等级
- 四、执行流程(非常重要)
- 第一步
- 第二步
- 第三步
- 五、带参数装饰器 + functools.wraps(推荐)
- 六、经典应用场景(非常重要)
- 1 日志控制
- 2 权限控制
- 3 重试机制(工程中非常常见)
- 4 计时器(深度学习训练常用)
- 5 参数检查
- 七、进阶:带参数 + 类装饰器
- 八、工程中最常见的写法总结
- 九、一句话总结
在 Python 中,带参数的装饰器(decorator with arguments)本质上是三层函数结构。很多人第一次看到会觉得复杂,其实理解它的核心思路就很简单:
装饰器要接收参数 → 就需要再包一层函数。
我会从4 个部分详细讲清楚:
1️⃣ 为什么需要带参数装饰器
2️⃣ 标准结构(必须掌握)
3️⃣ 逐步执行流程
4️⃣ 常见应用场景(实际开发)
一、为什么需要“带参数”的装饰器
普通装饰器:
deflogger(func):defwrapper(*args,**kwargs):print("函数开始执行")result=func(*args,**kwargs)print("函数执行结束")returnresultreturnwrapper使用:
@loggerdefadd(a,b):returna+b调用:
add(1,2)输出:
函数开始执行 函数执行结束但如果我们希望:
@logger(level="INFO")控制日志等级,就需要带参数装饰器。
二、带参数装饰器标准结构
核心结构:三层函数
defdecorator(arg1,arg2):defreal_decorator(func):defwrapper(*args,**kwargs):# 扩展逻辑result=func(*args,**kwargs)returnresultreturnwrapperreturnreal_decorator层级关系:
decorator(参数) ↓ real_decorator(func) ↓ wrapper(*args, **kwargs)三、完整示例(最经典)
例子:带日志等级
deflogger(level):defdecorator(func):defwrapper(*args,**kwargs):print(f"[{level}] 函数{func.__name__}开始执行")result=func(*args,**kwargs)print(f"[{level}] 函数{func.__name__}执行结束")returnresultreturnwrapperreturndecorator使用:
@logger("INFO")defadd(a,b):returna+b调用:
add(1,2)输出:
[INFO] 函数 add 开始执行 [INFO] 函数 add 执行结束四、执行流程(非常重要)
代码:
@logger("INFO")defadd(a,b):returna+bPython 实际执行:
第一步
执行:
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正确写法:
fromfunctoolsimportwrapsdeflogger(level):defdecorator(func):@wraps(func)defwrapper(*args,**kwargs):print(f"[{level}]{func.__name__}")returnfunc(*args,**kwargs)returnwrapperreturndecorator这样:
add.__name__ == "add"六、经典应用场景(非常重要)
1 日志控制
@log(level="DEBUG")deftrain():pass常见于:
- 深度学习训练
- API 调用
- 服务日志
2 权限控制
Web开发中常见:
@require_role("admin")defdelete_user():pass实现:
defrequire_role(role):defdecorator(func):defwrapper(user,*args,**kwargs):ifuser.role!=role:raisePermissionError("权限不足")returnfunc(user,*args,**kwargs)returnwrapperreturndecorator3 重试机制(工程中非常常见)
例如网络请求:
@retry(times=3)defrequest_api():pass实现:
defretry(times):defdecorator(func):defwrapper(*args,**kwargs):foriinrange(times):try:returnfunc(*args,**kwargs)exceptException:print(f"retry{i+1}")returnwrapperreturndecorator4 计时器(深度学习训练常用)
@timer(unit="ms")deftrain_step():pass实现:
importtimedeftimer(unit="s"):defdecorator(func):defwrapper(*args,**kwargs):start=time.time()result=func(*args,**kwargs)end=time.time()t=end-startifunit=="ms":t*=1000print(f"time:{t:.3f}{unit}")returnresultreturnwrapperreturndecorator5 参数检查
@validate_type(int,int)defadd(a,b):returna+b七、进阶:带参数 + 类装饰器
有时也用class decorator:
classLogger:def__init__(self,level):self.level=leveldef__call__(self,func):defwrapper(*args,**kwargs):print(self.level)returnfunc(*args,**kwargs)returnwrapper使用:
@Logger("INFO")八、工程中最常见的写法总结
标准模板(建议记住):
fromfunctoolsimportwrapsdefdecorator(arg):defreal_decorator(func):@wraps(func)defwrapper(*args,**kwargs):# beforeresult=func(*args,**kwargs)# afterreturnresultreturnwrapperreturnreal_decorator九、一句话总结
带参数装饰器本质就是:
三层函数结构参数层 → 装饰器层 → 包装函数层结构:
decorator(args) ↓ decorator(func) ↓ wrapper()