news 2026/4/3 6:27:59

Python 装饰器模式

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python 装饰器模式

Python 中的装饰器模式(Decorator Pattern)

装饰器模式是一种结构型设计模式,其核心目的是:
在不改变对象原有接口的情况下,动态地给对象添加额外职责(功能)

形象比喻:就像给礼物包装层层彩纸,每层包装都是一个“装饰”,礼物本身不变,但外观和功能增强了。

装饰器模式的优点
  • 比继承更灵活(可以运行时组合多个装饰)
  • 符合开闭原则:对扩展开放,对修改关闭
  • 支持职责的动态添加和移除
  • 避免子类爆炸(继承会导致类数量指数增长)
Python 中的特殊之处

Python 语言本身内置了装饰器语法@decorator,这让装饰器模式在 Python 中实现得异常简洁和优雅,甚至可以说是 Python 最常用的设计模式之一。

我们分两种情况讲解:

  1. 函数装饰器(最常见)
  2. 类/对象装饰器(经典 GoF 装饰器模式)

1. 函数装饰器(Python 最 Pythonic 的方式)

用于增强函数功能,常用于日志、计时、权限检查、缓存等。

importtimefromfunctoolsimportwraps# 装饰器:记录函数执行时间deftimer(func):@wraps(func)# 保留原函数的元信息(如 __name__)defwrapper(*args,**kwargs):start=time.time()result=func(*args,**kwargs)end=time.time()print(f"{func.__name__}执行耗时:{end-start:.4f}秒")returnresultreturnwrapper# 装饰器:打印日志deflogger(func):@wraps(func)defwrapper(*args,**kwargs):print(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] 调用{func.__name__},参数:{args},{kwargs}")returnfunc(*args,**kwargs)returnwrapper# 使用装饰器(支持多层装饰)@timer@loggerdeffactorial(n:int)->int:ifn==0:return1returnn*factorial(n-1)# 调用factorial(10)

输出示例

[2025-12-24 10:00:00] 调用 factorial,参数: (10,), {} factorial 执行耗时: 0.0001 秒

多层装饰顺序:从下往上执行(@logger 先包裹,再 @timer)。

带参数的装饰器(更高级)
defrepeat(times:int):defdecorator(func):@wraps(func)defwrapper(*args,**kwargs):for_inrange(times):result=func(*args,**kwargs)returnresultreturnwrapperreturndecorator@repeat(3)defgreet(name):print(f"Hello,{name}!")greet("Python")# 打印 3 次

2. 类装饰器(经典装饰器模式实现)

用于给对象动态添加职责,更接近 GoF 原意。

fromabcimportABC,abstractmethod# 组件接口(Component)classCoffee(ABC):@abstractmethoddefcost(self)->float:pass@abstractmethoddefdescription(self)->str:pass# 具体组件(Concrete Component)classSimpleCoffee(Coffee):defcost(self)->float:return5.0defdescription(self)->str:return"Simple Coffee"# 抽象装饰器(Decorator)classCoffeeDecorator(Coffee):def__init__(self,coffee:Coffee):self._coffee=coffeedefcost(self):returnself._coffee.cost()defdescription(self):returnself._coffee.description()# 具体装饰器:加牛奶classMilkDecorator(CoffeeDecorator):defcost(self):returnself._coffee.cost()+2.0defdescription(self):returnself._coffee.description()+", Milk"# 具体装饰器:加糖classSugarDecorator(CoffeeDecorator):defcost(self):returnself._coffee.cost()+0.5defdescription(self):returnself._coffee.description()+", Sugar"# 使用(动态组合)if__name__=="__main__":coffee=SimpleCoffee()print(coffee.description(),coffee.cost())# Simple Coffee 5.0coffee_with_milk=MilkDecorator(coffee)print(coffee_with_milk.description(),coffee_with_milk.cost())# + Milk 7.0coffee_with_milk_and_sugar=SugarDecorator(MilkDecorator(SimpleCoffee()))print(coffee_with_milk_and_sugar.description(),coffee_with_milk_and_sugar.cost())# Simple Coffee, Milk, Sugar 7.5

这正是经典装饰器模式的结构:装饰器持有被装饰对象,调用时层层转发并添加行为。


Python 中更简洁的类装饰器方式(函数式)

Python 允许直接用函数装饰类:

defdataclass_like(cls):# 简单实现类似 @dataclass 的 __repr__def__repr__(self):attrs=', '.join(f"{k}={v!r}"fork,vinself.__dict__.items())returnf"{cls.__name__}({attrs})"cls.__repr__=__repr__returncls@dataclass_likeclassPoint:def__init__(self,x,y):self.x=x self.y=y p=Point(1,2)print(p)# Point(x=1, y=2)

装饰器模式 vs 其他模式对比
模式目的是否改变接口
适配器转换接口改变
装饰器增强功能(保持原接口)不改变
代理控制访问(懒加载、权限等)不改变
组合静态组合对象-
实际常见应用场景
  • Web 框架(如 Flask)的@app.route('/')
  • Django 的@login_required
  • 缓存:@lru_cache(functools 内置)
  • 日志、权限、事务、性能监控
  • 中间件系统(如 FastAPI 的依赖注入)
注意事项
  • 装饰器顺序很重要(多层时)
  • 使用@wraps保留原函数元信息
  • 过多装饰可能影响调试和性能
  • 类装饰器会影响继承和类型检查

装饰器模式是 Python 中使用最频繁的设计模式之一,掌握它能让你写出更优雅、更可维护的代码!

如果你想看更多实战例子(如 Flask 路由装饰器实现、缓存装饰器、权限系统),或者如何实现带状态的装饰器,随时告诉我!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/1 16:55:28

knowledge-grab完整指南:快速下载国家中小学智慧教育资源

knowledge-grab完整指南:快速下载国家中小学智慧教育资源 【免费下载链接】knowledge-grab knowledge-grab 是一个基于 Tauri 和 Vue 3 构建的桌面应用程序,方便用户从 国家中小学智慧教育平台 (basic.smartedu.cn) 下载各类教育资源。 项目地址: http…

作者头像 李华
网站建设 2026/3/30 21:00:22

5分钟快速搭建个人服务器导航中心:Sun-Panel完全使用指南

5分钟快速搭建个人服务器导航中心:Sun-Panel完全使用指南 【免费下载链接】sun-panel 一个NAS导航面板、Homepage、浏览器首页。 项目地址: https://gitcode.com/gh_mirrors/su/sun-panel 想要让你的家庭服务器管理变得更简单高效吗?Sun-Panel作为…

作者头像 李华
网站建设 2026/3/28 22:21:33

为什么你的Open-AutoGLM远程连接总是超时?一文揪出根本原因

第一章:为什么你的Open-AutoGLM远程连接总是超时?一文揪出根本原因远程连接超时是使用 Open-AutoGLM 时最常见的问题之一,尤其在跨区域部署或复杂网络环境下尤为突出。尽管服务端已正常启动,客户端仍频繁遭遇连接中断或响应延迟&a…

作者头像 李华
网站建设 2026/4/3 5:52:02

基于ST7789的可穿戴设备屏幕驱动设计:入门必看

从零开始玩转ST7789:可穿戴设备屏幕驱动的实战指南 你有没有遇到过这样的情况? 花了几百块买来一块号称“高清彩屏”的0.96寸圆形TFT模块,接上STM32后却发现显示花屏、刷新卡顿、功耗爆表……最后只能扔在角落吃灰? 别急——这大…

作者头像 李华
网站建设 2026/3/30 12:39:22

《安卓逆向这档事》demo5 ----正己大佬

demo5 第五关网上找了很多,但是发现关于这一个版本的demo去除教程是一点没有,而且我也找不到原始的demo无法做到IO重定向。所以我也就直接通过jadx分析软件的java代码查找签名校验函数逻辑,然后通过NP管理器打开dex文件修改对应的smail代码&a…

作者头像 李华
网站建设 2026/3/6 14:29:32

智谱Open-AutoGLM插件使用秘籍:5个你不知道的高级技巧,第3个太惊艳

第一章:智谱Open-AutoGLM chrome 插件智谱Open-AutoGLM Chrome插件是一款专为提升网页端自然语言交互效率而设计的浏览器扩展工具。该插件基于AutoGLM大模型技术,集成于Chrome浏览器中,能够在用户浏览网页时实时提供语义理解、内容摘要、智能…

作者头像 李华