当前位置: 首页 > news >正文

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+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

正确写法:

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)returnwrapperreturndecorator

3 重试机制(工程中非常常见)

例如网络请求:

@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}")returnwrapperreturndecorator

4 计时器(深度学习训练常用)

@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}")returnresultreturnwrapperreturndecorator

5 参数检查

@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()
http://www.cnnetsun.cn/news/1496710.html

相关文章:

  • 收藏 | AI Agent 开发核心概念解析:从 LLM 到 Sub-agents,小白也能轻松入门
  • GLM库的ortho函数详解:从参数含义到矩阵运算可视化调试技巧
  • Grok-1开源项目实战指南:从环境搭建到性能优化的全方位解决方案
  • ViGEmBus虚拟手柄驱动:5个简单步骤实现专业级游戏控制体验
  • 跨平台实战:在QT Creator中一站式配置GStreamer开发环境
  • CTP期权操作实战指南:从查询到行权的完整流程
  • ROS机器人实战:修改LIO-SAM源码,一键保存TUM格式轨迹与点云地图
  • 从零到一:BepInEx游戏模组框架完全指南
  • 信奥赛C++提高组csp-s之组合数学专题课:第二类斯特林数
  • RabbitMQ 3.13.2安装踩坑实录:如何绕过rabbitmq-service.bat install code 1错误
  • 告别Windows依赖!用.NET 6+GTK轻松实现WinForm跨平台开发(Linux/Mac实战)
  • Grok-1开源项目实战指南:从零开始运行3140亿参数AI大模型
  • 3步解锁浏览器自动化革命:n8n-nodes-puppeteer让网页操作告别手动时代
  • 智能家居避坑指南:Arduino光敏电阻+继电器控制实战(LCD1602显示调试技巧)
  • Termius vs SecureCRT:为什么这款内置FTP的SSH工具更适合中文用户?
  • 保姆级教程:在Windows 11上搞定Webots R2022a与MATLAB R2022a的联合仿真环境配置
  • 离线环境解决方案:OpenClaw+GLM-4.7-Flash在内网科研机构的应用
  • 利用CSS动画打造动态语音发送波纹效果
  • 文科生也能玩转的AI自动化:我是如何用魔搭MCP和CherryStudio让Python代码自己发小红书的
  • 实战避坑指南:Cobalt Strike Beacon内存特征修改全流程(附Profile配置文件)
  • 别再只用M法了!手把手教你用Arduino和旋转编码器实现M/T法测速(附代码)
  • Synology Photos CPU驱动人脸识别补丁:解锁旧设备AI相册的终极方案
  • V8引擎源码魔改-彻底绕过无限debugger的终极方案
  • C语言结构体传参:从内存布局图看懂值传递、指针传递的底层差异(附VS调试技巧)
  • Fillinger终极指南:3分钟掌握Illustrator智能填充技巧
  • 新手必看!PADS Layout覆铜网格显示问题的5分钟快速修复指南
  • 基于Python的个人驾校预约管理系统毕业设计源码
  • 基于springboot商场物业管理系统设计与开发(源码+精品论文+答辩PPT等资料)
  • League-Toolkit智能工具高效使用指南:从入门到精通
  • OpenClaw到底能干嘛?30个落地案例,看完直接用