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

Python装饰器高级模式:从日志到AOP的完整实现

Python装饰器高级模式:从日志到AOP的完整实现

作者:Crown_22 | AI Agent & Hermes Agent 桌面程序开发者

前言

装饰器是Python中最优雅的特性之一,但大多数开发者只停留在@property@staticmethod的基础用法。实际上,装饰器可以实现日志、缓存、重试、权限控制、性能监控等众多高级功能。

本文将从装饰器的原理出发,逐步深入到高级模式,最终实现一个完整的AOP(面向切面编程)框架。


一、装饰器基础回顾

1.1 最简单的装饰器

defmy_decorator(func):defwrapper(*args,**kwargs):print("Before call")result=func(*args,**kwargs)print("After call")returnresultreturnwrapper@my_decoratordefsay_hello():print("Hello!")say_hello()# 输出:# Before call# Hello!# After call

1.2 带参数的装饰器

defrepeat(n):defdecorator(func):defwrapper(*args,**kwargs):for_inrange(n):result=func(*args,**kwargs)returnresultreturnwrapperreturndecorator@repeat(3)defgreet(name):print(f"Hello,{name}!")greet("World")# 输出:# Hello, World!# Hello, World!# Hello, World!

1.3 类装饰器

classLogger:def__init__(self,func):self.func=funcdef__call__(self,*args,**kwargs):print(f"Calling{self.func.__name__}")result=self.func(*args,**kwargs)print(f"Finished{self.func.__name__}")returnresult@Loggerdefadd(a,b):returna+bprint(add(1,2))# 输出:# Calling add# Finished add# 3

二、保留原函数信息

2.1 问题:装饰器丢失元信息

defmy_decorator(func):defwrapper(*args,**kwargs):returnfunc(*args,**kwargs)returnwrapper@my_decoratordefexample():"""这是文档字符串"""passprint(example.__name__)# 输出: wrapper(错误!)print(example.__doc__)# 输出: None(错误!)

2.2 解决方案:使用functools.wraps

fromfunctoolsimportwrapsdefmy_decorator(func):@wraps(func)defwrapper(*args,**kwargs):returnfunc(*args,**kwargs)returnwrapper@my_decoratordefexample():"""这是文档字符串"""passprint(example.__name__)# 输出: example(正确!)print(example.__doc__)# 输出: 这是文档字符串(正确!)

2.3 最佳实践:始终使用@wraps

fromfunctoolsimportwrapsfromtypingimportAny,Callable,TypeVar F=TypeVar('F',bound=Callable[...,Any])defmy_decorator(func:F)->F:@wraps(func)defwrapper(*args:Any,**kwargs:Any)->Any:returnfunc(*args,**kwargs)returnwrapper# type: ignore

三、实用装饰器模式

3.1 日志装饰器

基础版本

fromfunctoolsimportwrapsimportlogging logging.basicConfig(level=logging.INFO)logger=logging.getLogger(__name__)deflog_calls(func):@wraps(func)defwrapper(*args,**kwargs):logger.info(f"Calling{func.__name__}with args={args}, kwargs={kwargs}")try:result=func(*args,**kwargs)logger.info(f"{func.__name__}returned{result}")returnresultexceptExceptionase:logger.error(f"{func.__name__}raised{type(e).__name__}:{e}")raisereturnwrapper@log_callsdefadd(a:int,b:int)->int:returna+b add(1,2)# 输出:# INFO:__main__:Calling add with args=(1, 2), kwargs={}# INFO:__main__:add returned 3

高级版本:支持自定义日志级别和格式

fromfunctoolsimportwrapsfromtypingimportOptional,Callableimportloggingimporttimedeflog_calls(level:int=logging.INFO,message:Optional[str]=None,log_args:bool=True,log_result:bool=True,log_time:bool=False):"""高级日志装饰器 Args: level: 日志级别 message: 自定义消息模板 log_args: 是否记录参数 log_result: 是否记录返回值 log_time: 是否记录执行时间 """defdecorator(func:Callable)->Callable:@wraps(func)defwrapper(*args,**kwargs):logger=logging.getLogger(func.__module__)# 构建日志消息msg=messageorf"Calling{func.__name__}"iflog_args:msg+=f" with args={args}, kwargs={kwargs}"logger.log(level,msg)# 记录执行时间start_time=time.time()iflog_timeelseNonetry:result=func(*args,**kwargs)iflog_result:logger.log(level,f"{func.__name__}returned{result}")iflog_time:elapsed=time.time()-start_time logger.log(level,f"{func.__name__}took{elapsed:.4f}s")returnresultexceptExceptionase:logger.error(f"{func.__name__}raised{type(e).__name__
http://www.gsyq.cn/news/1386355.html

相关文章:

  • 基于LM22678的树莓派硬盘专用电源设计:解决供电不稳与电流冲击
  • 从Office功能区的“局外人“到“掌控者“:Office RibbonX Editor深度指南
  • 如何在5分钟内免费搭建你的第一个工业级虚拟PLC系统
  • Linux设置命令行无操作超时退出的解决方案
  • 基于THAT1240芯片的平衡-非平衡音频转换器设计与实践
  • 基于ESP32/ESP8266的本地化无线门铃通知系统设计与实现
  • DIY无线电控制闹钟:自动对时、自适应亮度与家庭自动化集成
  • DeepSeek代码审计避坑手册:5类被90%团队忽略的AI模型注入风险及实时拦截方案
  • Codex 与 Claude Code 安装配置教程
  • 宝藏合集!2026AI写作辅助网站大盘点(覆盖 99% 毕业论文需求)
  • 技术赋能智慧新能源|黎阳之光风电叶片光栅载荷+声纹AI智能监测技术落地应用
  • 从Arduino到PCB:ATmega328P+ESP8266 Wi-Fi控制器实战开发全解析
  • 2026年视频剪辑就业培训TOP5靠谱机构盘点:短视频剪辑培训、短视频培训、视频剪辑制作培训、视频剪辑线上培训选择指南 - 优质品牌商家
  • 【前端开发者生存报告2024】:92%的重构返工源于忽略这3个Lovable前置指标
  • 华为光猫配置解密工具进阶指南:深度解析与实战应用
  • 性能优化实战:Unity中Mesh Collider、Box Collider怎么选?附移动端适配建议
  • 阜阳靠谱的断桥铝系统门窗工厂
  • 2026中巴双边贸易格局与产品结构全景分析
  • OpenCore Legacy Patcher完整方案:如何在老旧Mac上安装最新macOS的实用指南
  • 告别依赖地狱:用Anaconda虚拟环境一键搞定HiC-Pro 3.1.0安装(附细菌基因组实战配置)
  • 凸优化理论导向的阵列天线方向图综合优化算法【附代码】
  • 航空发动机分布式控制系统关键技术【附代码】
  • 告别Unity默认Text!TextMeshPro图文混排实战:从表情包到聊天系统
  • AIMeter:AI工作负载能耗与碳足迹监测工具详解
  • 趋势科技提醒注意已遭利用的 Apex One 0day 漏洞
  • 避坑指南:从下载到跑通第一个Cypher查询,Neo4j社区版在Windows/Mac上的完整配置流程
  • 扩散模型优化:OptiPrune解决语义偏差与计算效率问题
  • Python自动连连看:计算机视觉如何实现游戏外挂的终极指南
  • 自制BLE112串口编程器:基于Bootloader的免调试器烧录方案
  • 【2026最新】应对Turnitin查重:实测5大英文查降AI宝藏工具,一站式搞定初稿