news 2026/6/14 14:21:38

Python 观察者模式

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python 观察者模式

Python 中的观察者模式(Observer Pattern)

观察者模式是一种行为型设计模式,其核心目的是:
定义对象间的一种一对多依赖关系,当一个对象(主题/被观察者)的状态发生改变时,所有依赖它的对象(观察者)都得到通知并自动更新

形象比喻:就像订阅报纸——你(观察者)订阅了报纸(主题),每当有新报纸出版,邮递员就会自动送到你家。

观察者模式的优点
  • 实现主题和观察者之间的松耦合(主题只知道观察者列表,不关心具体类型)
  • 支持广播通信(一个变化通知多个对象)
  • 符合“开闭原则”:新增观察者无需修改主题代码
典型应用场景
  • GUI 系统:按钮点击通知多个监听器
  • 事件驱动编程(如 tkinter、PyQt 的信号槽)
  • 发布-订阅系统(消息队列、事件总线)
  • 数据变更通知(如股票价格更新、天气预报)
  • MVC 架构中的 View 更新
Python 实现示例:股票价格监控
fromabcimportABC,abstractmethodfromtypingimportList# 观察者接口(Observer)classObserver(ABC):@abstractmethoddefupdate(self,subject):pass# 具体观察者:图表显示classChartDisplay(Observer):defupdate(self,subject):print(f"【图表】股票价格更新:{subject.stock_name}= ${subject.price:.2f}")# 具体观察者:短信通知classSMSAlert(Observer):def__init__(self,phone_number:str):self.phone_number=phone_numberdefupdate(self,subject):ifsubject.price>150:# 价格超过150时才发短信print(f"【短信】发送到{self.phone_number}{subject.stock_name}已突破 ${subject.price:.2f}!")# 具体观察者:邮件通知classEmailAlert(Observer):def__init__(self,email:str):self.email=emaildefupdate(self,subject):print(f"【邮件】发送到{self.email}{subject.stock_name}最新价格 ${subject.price:.2f}")# 主题(Subject / Observable)classStock:def__init__(self,name:str,price:float):self.stock_name=name self.price=price self._observers:List[Observer]=[]defattach(self,observer:Observer):ifobservernotinself._observers:self._observers.append(observer)print(f"{observer.__class__.__name__}已订阅{self.stock_name}")defdetach(self,observer:Observer):ifobserverinself._observers:self._observers.remove(observer)print(f"{observer.__class__.__name__}已取消订阅{self.stock_name}")defnotify(self):print(f"通知所有观察者...")forobserverinself._observers:observer.update(self)defset_price(self,new_price:float):ifnew_price!=self.price:self.price=new_priceprint(f"{self.stock_name}价格变动 → ${new_price:.2f}")self.notify()# 客户端使用if__name__=="__main__":# 创建股票(主题)apple_stock=Stock("AAPL",145.0)# 创建观察者chart=ChartDisplay()sms=SMSAlert("138-1234-5678")email=EmailAlert("investor@example.com")# 订阅apple_stock.attach(chart)apple_stock.attach(sms)apple_stock.attach(email)print("\n--- 第一次价格更新 ---")apple_stock.set_price(152.0)# 触发通知print("\n--- 第二次价格更新 ---")apple_stock.set_price(148.0)# 短信不触发(未超150)print("\n--- 取消短信订阅 ---")apple_stock.detach(sms)print("\n--- 第三次价格更新 ---")apple_stock.set_price(160.0)# 只有图表和邮件收到通知

输出

ChartDisplay 已订阅 AAPL SMSAlert 已订阅 AAPL EmailAlert 已订阅 AAPL --- 第一次价格更新 --- AAPL 价格变动 → $152.00 通知所有观察者... 【图表】股票价格更新:AAPL = $152.00 【短信】发送到 138-1234-5678:AAPL 已突破 $152.00! 【邮件】发送到 investor@example.com:AAPL 最新价格 $152.00 --- 第二次价格更新 --- AAPL 价格变动 → $148.00 通知所有观察者... 【图表】股票价格更新:AAPL = $148.00 【邮件】发送到 investor@example.com:AAPL 最新价格 $148.00 --- 取消短信订阅 --- SMSAlert 已取消订阅 AAPL --- 第三次价格更新 --- AAPL 价格变动 → $160.00 通知所有观察者... 【图表】股票价格更新:AAPL = $160.00 【邮件】发送到 investor@example.com:AAPL 最新价格 $160.00
Pythonic 更简洁实现:使用属性装饰器

Python 中可以用@property实现自动通知:

classObservable:def__init__(self):self._observers=[]defattach(self,observer):self._observers.append(observer)defdetach(self,observer):self._observers.remove(observer)defnotify(self):forobserverinself._observers:observer(self)# 直接传整个对象classStock(Observable):def__init__(self,name,price):super().__init__()self._name=name self._price=price@propertydefprice(self):returnself._price@price.setterdefprice(self,value):self._price=value self.notify()# 自动通知# 使用stock=Stock("TSLA",800)stock.attach(lambdas:print(f"价格更新:{s._name}= ${s._price}"))stock.price=850# 自动触发
内置支持:事件库

Python 标准库没有内置观察者,但第三方库很成熟:

  • blinker:轻量级信号系统
  • PyDispatcher:经典事件分发
  • GUI 框架(如tkinterPyQtPySide)自带信号槽机制
观察者模式结构总结
角色说明
Subject主题,维护观察者列表,提供 attach/detach/notify
Observer抽象观察者,定义 update 接口
ConcreteSubject具体主题(如 Stock),状态变化时调用 notify
ConcreteObserver具体观察者(如 ChartDisplay、SMSAlert)
观察者模式 vs 发布-订阅模式
  • 观察者模式:主题直接持有观察者引用(紧耦合于同一进程)
  • 发布-订阅(Pub/Sub):通过消息中间件解耦(支持分布式,如 Redis、Kafka)
Python 中的实用建议
  • 小型项目:手写观察者(如上例)
  • 中型项目:使用@property+ 回调列表
  • GUI/事件驱动:直接用框架的信号机制
  • 大型/分布式:使用消息队列(Celery、RabbitMQ)
注意事项
  • 通知顺序不确定(除非显式排序)
  • 避免在 update 中修改主题状态(可能无限循环)
  • 多线程时需加锁保护观察者列表
  • 取消订阅很重要(避免内存泄漏)

观察者模式是事件驱动编程的核心,在 Python 的 GUI、Web 框架、异步系统中无处不在。

如果你想看更高级的例子(如多线程安全观察者、结合 asyncio 的异步通知、使用 blinker 库的信号系统),或者与其他模式结合(如观察者 + 策略),随时告诉我!

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

错过等一年!Open-AutoGLM 2.0正式上线GitHub,这些功能你必须掌握

第一章:错过等一年!Open-AutoGLM 2.0正式发布Open-AutoGLM 2.0 正式上线,标志着自动化大模型应用开发迈入全新阶段。该版本在性能、易用性和扩展性方面实现全面升级,专为开发者与企业用户打造高效、灵活的AI解决方案构建平台。核心…

作者头像 李华
网站建设 2026/6/15 12:37:59

破解“写作围城”:当期刊投稿遇上行家级AI协作者

文献迷雾中不再焦虑,智能工具重构写作全流程的效率与质量深夜的实验室,屏幕上摊着十几个窗口——文献PDF、草稿文档、数据表格和格式混乱的参考文献列表,学者们正试图从数字碎片中拼凑论文的完整形态,这种场景几乎成为科研通病。传…

作者头像 李华
网站建设 2026/6/14 10:25:10

12、GAN技术:从渐进式生成到半监督学习的突破

GAN技术:从渐进式生成到半监督学习的突破 1. 渐进式生成对抗网络(Progressive GAN)的实际应用 1.1 医学影像合成的卓越成果 在医学领域,研究人员利用大量的医学乳腺X光片数据集,借助渐进式生成对抗网络(Progressive GAN,简称PGGAN)技术,成功生成了分辨率高达1280 …

作者头像 李华
网站建设 2026/6/15 12:47:53

17、CycleGAN与对抗样本:原理、训练与应用

CycleGAN与对抗样本:原理、训练与应用 1. CycleGAN概述 CycleGAN是一种强大的图像到图像转换模型,它能够在无需配对图像数据的情况下,实现不同领域之间的图像转换,例如将苹果转换为橙子,反之亦然。下面我们将详细介绍CycleGAN的构建、训练和应用。 1.1 构建生成器 生成…

作者头像 李华
网站建设 2026/5/29 19:35:01

18、对抗样本:从原理到防御的全面解析

对抗样本:从原理到防御的全面解析 1. 训练数据的挑战 在处理图像数据时,即使是同一类别的图像,当拍摄角度稍有变化,它们之间的差异也可能很大。以一个包含100,000个300300的RGB图像的训练集为例,我们需要处理270,000个维度的数据。当考虑所有可能的图像(而非实际观察到…

作者头像 李华