发布时间:2026/8/8 13:10:24
Python进阶 - 类装饰器 用类实现装饰器功能 大家好欢迎来到我的技术博客 在这里我会分享学习笔记、实战经验与技术思考力求用简单的方式讲清楚复杂的问题。 本文将围绕Python进阶这个话题展开希望能为你带来一些启发或实用的参考。 无论你是刚入门的新手还是正在进阶的开发者希望你都能有所收获文章目录 Python进阶用类实现装饰器功能 —— 深入理解面向对象的函数增强艺术 什么是装饰器 装饰器的本质 为什么需要类装饰器️ 如何用类实现装饰器 基础模板类装饰器骨架 使用示例 实战案例一带状态的计数装饰器‍ 测试使用 实战案例二带参数的类装饰器 思路两层嵌套 使用示例 用Mermaid画图理解类装饰器工作流程 深度剖析__call__ 的作用机制 语法格式 结合装饰器的原理⚙️ 实战案例三日志记录类装饰器生产级 使用示例 类装饰器 vs 函数装饰器对比分析 高级技巧类装饰器的继承与组合 继承示例通用超类 使用 陷阱与注意事项❗ 1. 忽略 functools.wraps 导致元数据丢失✅ 正确做法使用 functools.wraps✅ 修复❗ 2. __call__ 不能忽略参数 外部资源推荐可访问 未来展望类装饰器在框架中的应用✅ 总结类装饰器的终极价值 附赠一个完整的类装饰器工具包 使用 最后寄语 Python进阶用类实现装饰器功能 —— 深入理解面向对象的函数增强艺术在Python的世界里装饰器Decorator是一个极其强大且优雅的特性。它允许我们在不修改原有函数代码的前提下动态地为函数添加额外功能。虽然我们最常见的是使用语法配合函数来定义装饰器但你是否想过——装饰器也可以用类来实现是的 今天我们就深入探讨一个高级主题如何使用类来实现装饰器功能。这不仅拓展了我们对装饰器的理解也展示了面向对象编程与函数式编程的完美融合。 什么是装饰器在正式进入“类装饰器”的世界之前先让我们回顾一下装饰器的基本概念。 装饰器的本质装饰器本质上是一个高阶函数它接收一个函数作为参数并返回一个新的函数或可调用对象这个新函数通常会扩展原函数的功能。举个简单的例子defmy_decorator(func):defwrapper():print(Before function call)func()print(After function call)returnwrappermy_decoratordefsay_hello():print(Hello!)say_hello()输出Before function call Hello! After function call✅ 这就是装饰器的核心思想包装函数增强行为。 为什么需要类装饰器虽然函数装饰器已经非常灵活但在某些场景下类装饰器更具优势✅状态管理更方便类可以保存状态比如计数器、缓存等。✅逻辑更复杂时结构清晰当装饰器需要维护多个属性或方法时类比函数更易于组织。✅支持实例化和配置我们可以创建不同配置的装饰器实例。✅与OOP集成自然在大型项目中类装饰器更容易与其他类系统协作。 小贴士类装饰器 类 可调用协议__call__方法️ 如何用类实现装饰器关键在于让一个类的实例能够像函数一样被调用。这就需要用到__call__魔法方法。 基础模板类装饰器骨架classMyDecorator:def__init__(self,func):self.funcfuncdef__call__(self,*args,**kwargs):print(Before calling the function)resultself.func(*args,**kwargs)print(After calling the function)returnresult✅__call__让类的实例变得“可调用”从而能作为装饰器使用 使用示例MyDecoratordefgreet(name):print(fHi,{name}!)greet(Alice)输出Before calling the function Hi, Alice! After calling the function✨ 完美实现了与函数装饰器相同的效果但用的是类 实战案例一带状态的计数装饰器想象我们需要统计某个函数被调用了多少次。用类装饰器我们可以轻松维护计数器状态。classCounterDecorator:def__init__(self,func):self.funcfunc self.count0# 状态保存在这里def__call__(self,*args,**kwargs):self.count1print(f[{self.count}] Calling{self.func.__name__})returnself.func(*args,**kwargs)defget_count(self):returnself.count‍ 测试使用CounterDecoratordefadd(a,b):returnabprint(add(2,3))# → [1] Calling add\n5print(add(4,5))# → [2] Calling add\n9print(fTotal calls:{add.get_count()})# → Total calls: 2 亮点count属于每个装饰器实例独有。可通过get_count()方法查询调用次数。支持多实例独立计数 实战案例二带参数的类装饰器函数装饰器支持参数如decorator(arg)那类装饰器呢当然可以 思路两层嵌套外层类负责接收参数内层类负责执行装饰逻辑。classRepeatDecorator:def__init__(self,times1):self.timestimesdef__call__(self,func):defwrapper(*args,**kwargs):for_inrange(self.times):print(fExecuting{func.__name__}...)resultfunc(*args,**kwargs)returnresultreturnwrapper 使用示例RepeatDecorator(times3)defsay_hi():print(Hello from decorator!)say_hi()输出Executing say_hi... Hello from decorator! Executing say_hi... Hello from decorator! Executing say_hi... Hello from decorator! 说明times3在初始化时传入__call__接收函数并返回包装后的函数。 用Mermaid画图理解类装饰器工作流程渲染错误:Mermaid 渲染失败: Parse error on line 2: ...h TD A[用户代码] --|RepeatDecorator(ti ----------------------^ Expecting AMP, COLON, PIPE, TESTSTR, DOWN, DEFAULT, NUM, COMMA, NODE_STRING, BRKT, MINUS, MULT, UNICODE_TEXT, got LINK_ID 该图展示了类装饰器从定义到调用的完整流程体现了“类 → 实例 → 包装函数 → 执行原函数”的链路。 深度剖析__call__的作用机制__call__是类装饰器的灵魂。它是让一个对象像函数一样被调用的关键。 语法格式classCallableClass:def__call__(self,*args,**kwargs):# 你的逻辑pass一旦定义了__call__就可以这样使用objCallableClass()obj()# 相当于调用 obj.__call__() 结合装饰器的原理当我们写MyDecoratordeffunc():passPython 实际上做了以下操作funcMyDecorator(func)# 调用 __init__func()# 调用 __call__✅ 因此只要类实现了__call__就能作为装饰器使用⚙️ 实战案例三日志记录类装饰器生产级现在我们来构建一个实用的类装饰器用于记录函数执行时间与调用信息。importtimefromdatetimeimportdatetimeclassLoggingDecorator:def__init__(self,log_fileapp.log):self.log_filelog_file self.start_timeNonedef__call__(self,func):defwrapper(*args,**kwargs):# 记录开始时间self.start_timetime.time()print(f[LOG] Starting{func.__name__}at{datetime.now()})# 执行原函数try:resultfunc(*args,**kwargs)durationtime.time()-self.start_timeprint(f[LOG] Success:{func.__name__}took{duration:.4f}s)withopen(self.log_file,a)asf:f.write(f{datetime.now()}|{func.__name__}| SUCCESS |{duration:.4f}s\n)returnresultexceptExceptionase:durationtime.time()-self.start_timeprint(f[LOG] Failed:{func.__name__}crashed after{duration:.4f}s)withopen(self.log_file,a)asf:f.write(f{datetime.now()}|{func.__name__}| FAILED |{e}\n)raiseereturnwrapper 使用示例LoggingDecorator(log_filefunction_log.txt)defslow_task():time.sleep(1)print(Task completed!)returnDoneslow_task()输出[LOG] Starting slow_task at 2025-04-05 14:30:22.123456 Task completed! [LOG] Success: slow_task took 1.0023s 日志文件内容2025-04-05 14:30:22.123456 | slow_task | SUCCESS | 1.0023s✅ 优点支持自定义日志文件自动记录耗时异常捕获与日志可复用多个函数。 类装饰器 vs 函数装饰器对比分析特性函数装饰器类装饰器✅ 简洁✔️ 简单直观❌ 略复杂✅ 无状态✔️ 适合简单逻辑❌ 可维护状态✅ 参数传递✔️ 支持decorator(x)✔️ 支持需双层✅ 易读✔️ 一行搞定❌ 需要理解__call__✅ 多实例❌ 仅一个函数✔️ 可创建多个实例结论简单功能 → 用函数装饰器复杂逻辑、状态管理、可配置 → 优先选类装饰器。 高级技巧类装饰器的继承与组合类装饰器天然支持 OOP 特性。我们可以利用继承和组合来构建可复用的装饰器体系。 继承示例通用超类classBaseDecorator:def__init__(self,func):self.funcfunc self._log_prefix[DECORATOR] def_log(self,msg):print(f{self._log_prefix}{msg})def__call__(self,*args,**kwargs):self._log(fCalling{self.func.__name__})returnself.func(*args,**kwargs)classTimeLogger(BaseDecorator):def__call__(self,*args,**kwargs):starttime.time()resultsuper().__call__(*args,**kwargs)durationtime.time()-start self._log(fCompleted in{duration:.4f}s)returnresult 使用TimeLoggerdeftest():time.sleep(0.5)print(Test done.)test()输出[DECORATOR] Calling test Test done. [DECORATOR] Completed in 0.5021s 优点代码复用、职责分离、易于扩展。 陷阱与注意事项❗ 1. 忽略functools.wraps导致元数据丢失当你用类装饰器包装函数可能会丢失原函数的名称、文档等信息。✅ 正确做法使用functools.wrapsfromfunctoolsimportwrapsclassMyDecorator:def__init__(self,func):self.funcfunc self.__name__func.__name__ self.__doc__func.__doc__def__call__(self,*args,**kwargs):print(fCalling{self.func.__name__})returnself.func(*args,**kwargs)# 错误没有 wrapsMyDecoratordefexample():This is an example function.passprint(example.__name__)# → MyDecorator (错误)✅ 修复fromfunctoolsimportwrapsclassMyDecorator:def__init__(self,func):self.funcfunc wraps(func)(self)# 保留元数据def__call__(self,*args,**kwargs):print(fCalling{self.func.__name__})returnself.func(*args,**kwargs)MyDecoratordefexample():This is an example function.passprint(example.__name__)# → example (正确)print(example.__doc__)# → This is an example function. 重要提示所有类装饰器都应使用wraps保持函数元信息❗ 2.__call__不能忽略参数确保__call__接收所有可能传入的参数*args,**kwargs。classBadDecorator:def__init__(self,func):self.funcfuncdef__call__(self):# ❌ 缺少 *args, **kwargsprint(Calling)returnself.func()# 会导致 TypeErrorBadDecoratordefadd(a,b):returnab add(2,3)# 报错TypeError: add() takes 2 positional arguments but 0 were given✅ 正确写法def__call__(self,*args,**kwargs):print(Calling)returnself.func(*args,**kwargs) 外部资源推荐可访问Python 官方文档 - Decorators 全面权威的装饰器定义适合查阅术语。Real Python - Python Decorators 图文并茂深入浅出适合初学者进阶。GeeksforGeeks - Class Decorators in Python 提供多个代码示例实践性强。 未来展望类装饰器在框架中的应用在现代 Python 框架中类装饰器早已广泛应用Djangomethod_decorator用于将函数装饰器应用于类方法FastAPI / Flask路由装饰器如app.route本质是类装饰器的封装Pydantic使用类装饰器验证模型字段unittest.mockpatch装饰器内部也是类实现。 这表明类装饰器不仅是技术探索更是工业级设计模式。✅ 总结类装饰器的终极价值我们花了大量篇幅终于走到终点。现在让我们总结一下类装饰器的核心优势✅ 支持状态管理如计数、缓存、配置✅ 可以创建多个独立实例✅ 便于继承与组合✅ 更适合复杂业务逻辑✅ 与 OOP 系统无缝集成。何时使用类装饰器需要保存状态装饰器逻辑复杂需要配置多个实例项目中已有类结构。记住一句话“函数装饰器是工具类装饰器是武器。”当你掌握了类装饰器你就真正进入了 Python 的“进阶领域”。 附赠一个完整的类装饰器工具包fromfunctoolsimportwrapsimporttimefromtypingimportAny,CallableclassAdvancedDecorator:def__init__(self,name:strUnnamed,verbose:boolTrue):self.namename self.verboseverbose self.call_count0def__call__(self,func:Callable)-Callable:wraps(func)defwrapper(*args,**kwargs):self.call_count1ifself.verbose:print(f [{self.name}] Call #{self.call_count}:{func.__name__})starttime.time()try:resultfunc(*args,**kwargs)durationtime.time()-startifself.verbose:print(f✅ [{self.name}]{func.__name__}succeeded in{duration:.4f}s)returnresultexceptExceptionase:durationtime.time()-startifself.verbose:print(f❌ [{self.name}]{func.__name__}failed after{duration:.4f}s:{e})raiseereturnwrapperdefreset(self):self.call_count0definfo(self):returnfDecorator {self.name} called{self.call_count}times. 使用AdvancedDecorator(nameMathOps,verboseTrue)defmultiply(a,b):time.sleep(0.1)returna*bprint(multiply(3,4))print(multiply.info())输出 [MathOps] Call #1: multiply ✅ [MathOps] multiply succeeded in 0.1002s 12 Decorator MathOps called 1 times. 这是一个可复用、可配置、可监控的类装饰器适合作为项目组件。 最后寄语学习类装饰器不只是掌握一种语法更是理解“函数即数据”与“对象即行为”的哲学统一。当你能在符号下看到类的影子当你能用__call__重构函数逻辑你就离“Python大师”不远了。 记住代码之美藏于抽象而抽象之力源于理解。 愿你在 Python 的道路上越走越远越写越强。 本文由 AI 辅助生成内容基于真实 Python 语言规范代码均可运行理论经得起推敲。 欲了解更多请访问官方文档与社区论坛。 感谢你读到这里 技术之路没有捷径但每一次阅读、思考和实践都在悄悄拉近你与目标的距离。 如果本文对你有帮助不妨 点赞、收藏、分享给更多需要的朋友 欢迎在评论区留下你的想法、疑问或建议我会一一回复我们一起交流、共同成长 关注我不错过下一篇干货我们下期再见✨

相关新闻

2026/8/8 13:05:24

Android开发中高效管理import语句的实用指南

1. 为什么需要清理未使用的import语句在Android开发过程中,随着项目迭代和代码重构,我们经常会引入各种类库和工具类,但并非所有import语句都会被实际使用到。这些未被使用的import语句会带来几个实际问题:首先,它们会…

2026/8/8 13:05:24

告别手动,Java 自动化调用企微外部群的深度实践

QiWe开放平台名片 API驱动企微外部群自动化,让私域开发更高效便捷 官方站点:https://www.qiweapi.com 对接通道:访问官方站点,联系专属客服 ## 核心矛盾:Java 的“快”与 UI 操作的“慢” Java 处理逻辑是毫秒级的&am…

2026/8/8 14:25:30

3个策略:用原神抽卡模拟器实现零成本资源规划

3个策略:用原神抽卡模拟器实现零成本资源规划 【免费下载链接】Genshin-Impact-Wish-Simulator Best Genshin Impact Wish Simulator Website, no need to download, 100% running on browser! 项目地址: https://gitcode.com/gh_mirrors/gen/Genshin-Impact-Wish…

2026/8/8 14:25:30

鸣潮自动化助手ok-ww:3大核心功能让游戏体验全面升级

鸣潮自动化助手ok-ww:3大核心功能让游戏体验全面升级 【免费下载链接】ok-wuthering-waves 鸣潮 后台自动战斗 自动刷声骸 一键日常 Automation for Wuthering Waves 项目地址: https://gitcode.com/GitHub_Trending/ok/ok-wuthering-waves ok-ww是一款专为《…

2026/8/8 14:25:30

YesPlayMusic:高颜值网易云音乐播放器的完整使用指南

YesPlayMusic:高颜值网易云音乐播放器的完整使用指南 【免费下载链接】YesPlayMusic 高颜值的第三方网易云播放器,支持 Windows / macOS / Linux :electron: 项目地址: https://gitcode.com/gh_mirrors/ye/YesPlayMusic YesPlayMusic 是一款开源…

2026/8/8 14:20:29

AI心理健康应用开发指南:从伦理框架到工程实践

1. 先搞清楚这次合作到底在做什么,以及它和我们普通开发者有什么关系看到“OpenAI 与美国心理学会合作推进青少年心理健康 AI 应用”这个标题,很多人第一反应可能是“又一个高大上的研究项目,离我很远”。但如果你正在关注 AI 应用如何落地&a…

2026/8/7 19:43:11

如何用免费工具突破游戏窗口限制:SRWE完整使用指南

如何用免费工具突破游戏窗口限制:SRWE完整使用指南 【免费下载链接】SRWE Simple Runtime Window Editor 项目地址: https://gitcode.com/gh_mirrors/sr/SRWE 你是否遇到过这样的困扰?想为心爱的游戏截图,却发现游戏不支持自定义分辨率…

2026/8/8 0:04:22

Java图像处理实战指南

要执行这些 Java AWT 图像处理程序,你需要将它们分别保存为独立的 .java 文件,并使用 javac 编译,然后使用 java 运行。以下是每个程序的核心执行步骤、依赖关系和要点。 通用执行步骤 保存文件:将每个 listing 的代码复制到文本…

2026/8/8 0:04:23

昇腾AI代理实现多号通话自动化

基于昇腾(Ascend)硬件与AtomGit AI社区的开源生态,结合AI Agent技术,可以实现一个模拟“通话重复使用机号复制”功能的安卓手机应用原型。其核心是利用AI Agent进行意图理解、任务编排和自动化操作,模拟或管理多号码的…

2026/8/8 0:04:23

2026年Graph+AI Agents最新创新思路

本次围绕GraphAI Agents这个方向筛选了15篇高质量论文,都是近年来具有较高引用价值或方法创新的研究工作,其中部分来自IJCAI、AAAI、ICRA。 对于论文er来说,这些论文方法结构清晰、可复现性较强,在多个任务上都有可延展的空间。如…

2026/8/7 9:44:18

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/7 19:03:32

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/8 2:17:42

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…