Python中的观察者模式及其应用

观察者模式是设计模式之一,实现一对多依赖,当主题状态变化时通知所有观察者更新。在Python中,通过自定义接口或内置模块实现观察者模式,可提高程序灵活性和扩展性,尤其适用于状态变化时触发操作的场景,如事件驱动系统、数据同步、发布/订阅系统和气象监测系统等。观察者模式具有松耦合、灵活、可复用的优点,但也需注意其可能带来的开闭原则挑战、效率、循环依赖等问题。

一、引言

观察者模式(Observer Pattern)是设计模式中的一种行为型模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一主题对象,当主题对象状态发生改变时,会通知所有观察者对象,使它们能够自动更新自己。这种模式使得目标和观察者之间松散耦合,因为观察者只知道他们需要关注的主题发生了变化,而不必了解变化的具体细节。

在Python编程中,观察者模式可以极大地提高程序的可扩展性和灵活性,尤其适用于那些需要在状态变化时执行特定操作的场景。

二、观察者模式的实现

在Python中,我们可以使用内置的collections.abc模块中的MutableSequence抽象基类,或者自定义一个简单的接口来实现观察者模式。下面是一个基于自定义接口的基本实现:

import abc# 定义观察者接口
class Observer(metaclass=abc.ABCMeta):@abc.abstractmethoddef update(self, subject, message):pass# 定义被观察者(主题)类
class Subject:def __init__(self):self._observers = []def attach(self, observer):self._observers.append(observer)def detach(self, observer):self._observers.remove(observer)def notify(self, message):for observer in self._observers:observer.update(self, message)# 实现具体的观察者
class ConcreteObserver(Observer):def update(self, subject, message):print(f"接收到主题({subject})的通知: {message}")# 使用示例
if __name__ == "__main__":subject = Subject()observer1 = ConcreteObserver()observer2 = ConcreteObserver()subject.attach(observer1)subject.attach(observer2)subject.notify("状态已更新")

三、观察者模式的应用场景

3.1 事件驱动系统

观察者模式可以很好地应用于事件驱动编程,尤其是在构建GUI应用程序、网络I/O处理和异步任务调度等领域。下面是一个简化的事件驱动编程中的观察者模式实现,模拟了一个简单的事件总线(Event Bus)系统:

import abc
from typing import Callableclass Event(metaclass=abc.ABCMeta):passclass MyCustomEvent(Event):def __init__(self, data):self.data = dataclass EventHandler(metaclass=abc.ABCMeta):@abc.abstractmethoddef handle(self, event: Event):passclass EventBus:def __init__(self):self._handlers = {}def register_handler(self, event_type: type, handler: EventHandler):if event_type not in self._handlers:self._handlers[event_type] = []self._handlers[event_type].append(handler)def unregister_handler(self, event_type: type, handler: EventHandler):if event_type in self._handlers and handler in self._handlers[event_type]:self._handlers[event_type].remove(handler)def publish(self, event: Event):event_type = type(event)if event_type in self._handlers:for handler in self._handlers[event_type]:handler.handle(event)# 具体的事件处理器实现
class CustomEventHandler(EventHandler):def handle(self, event: Event):if isinstance(event, MyCustomEvent):print(f"处理自定义事件,数据为: {event.data}")# 应用场景
if __name__ == "__main__":bus = EventBus()custom_handler = CustomEventHandler()# 注册事件处理器bus.register_handler(MyCustomEvent, custom_handler)# 发布事件custom_event = MyCustomEvent("Hello, World!")bus.publish(custom_event)

在这个例子中,EventBus作为一个中心组件,负责管理和分发事件。EventHandler是观察者接口,任何想要处理事件的类都需要实现这个接口。当有事件发布到事件总线上时,事件总线会查找对应类型的事件处理器,并调用它们的handle方法来处理事件。

MyCustomEvent是具体的事件类型,而CustomEventHandler则是针对该事件类型的具体处理器。在主程序中,我们创建了一个事件总线实例,注册了一个自定义事件处理器,然后发布了一个自定义事件。发布事件后,自定义事件处理器接收到事件并进行了处理。这就是观察者模式在事件驱动编程中的基本应用。

3.2 数据同步

在数据同步的场景中,观察者模式可以用来实现在数据源发生更改时,自动更新所有依赖于该数据的实体。以下是一个简单的Python实现,模拟了一个数据库表数据变化时通知多个订阅者进行数据同步的例子:

import abc# 定义观察者接口
class DataSyncObserver(metaclass=abc.ABCMeta):@abc.abstractmethoddef sync_data(self, updated_data):pass# 定义被观察者(数据源)
class DataSource:def __init__(self):self._observers = []def attach(self, observer: DataSyncObserver):self._observers.append(observer)def detach(self, observer: DataSyncObserver):self._observers.remove(observer)def update_data(self, new_data):self._data = new_dataself.notify_observers()def notify_observers(self):for observer in self._observers:observer.sync_data(self._data)# 实现具体的数据同步观察者
class CacheUpdater(DataSyncObserver):def __init__(self, cache):self.cache = cachedef sync_data(self, updated_data):print(f"CacheUpdater: Updating cache with new data: {updated_data}")self.cache.update(updated_data)class FrontendUpdater(DataSyncObserver):def __init__(self, frontend):self.frontend = frontenddef sync_data(self, updated_data):print(f"FrontendUpdater: Updating frontend with new data: {updated_data}")self.frontend.render(updated_data)# 应用场景
if __name__ == "__main__":source = DataSource()cache_updater = CacheUpdater(Cache())frontend_updater = FrontendUpdater(Frontend())source.attach(cache_updater)source.attach(frontend_updater)# 数据源数据发生更改source.update_data({"key": "value"})# 这里假设有Cache和Frontend类,分别代表缓存和前端展示组件
# 并且它们都有update方法用于更新数据

在这个例子中,DataSource是被观察者,它维护了一个观察者列表,并在数据更新时通过notify_observers方法通知所有观察者。CacheUpdaterFrontendUpdater都是数据同步观察者,它们实现了sync_data方法,当接收到数据源的更新通知时,会同步更新自身的缓存或前端显示数据。当数据源的update_data方法被调用时,所有已注册的观察者都会收到更新通知并执行同步操作。

3.3 发布/订阅系统

在发布/订阅(Publish/Subscribe)系统中,观察者模式是非常适合的,因为它可以很好地处理一对多的关系,即一个主题(发布者)可以有多个订阅者(观察者)。发布者发布消息时,所有订阅该主题的观察者都会收到通知。以下是一个基于Python实现的简化的发布/订阅系统示例:

import abc# 定义消息接口
class Message(metaclass=abc.ABCMeta):@abc.abstractmethoddef get_message(self) -> str:pass# 定义订阅者接口
class Subscriber(metaclass=abc.ABCMeta):@abc.abstractmethoddef receive_message(self, message: Message):pass# 定义发布/订阅系统的核心类
class PubSubSystem:def __init__(self):self._subscribers = {}def subscribe(self, topic: str, subscriber: Subscriber):if topic not in self._subscribers:self._subscribers[topic] = []self._subscribers[topic].append(subscriber)def unsubscribe(self, topic: str, subscriber: Subscriber):if topic in self._subscribers and subscriber in self._subscribers[topic]:self._subscribers[topic].remove(subscriber)def publish(self, message: Message):topic = message.get_topic()if topic in self._subscribers:for subscriber in self._subscribers[topic]:subscriber.receive_message(message)# 实现具体的消息类和订阅者类
class NewsMessage(Message):def __init__(self, title, content):self.title = titleself.content = contentdef get_topic(self) -> str:return "news"def get_message(self) -> str:return f"Title: {self.title}, Content: {self.content}"class NewsSubscriber(Subscriber):def receive_message(self, message: Message):if isinstance(message, NewsMessage):print(f"NewsSubscriber received news: {message.get_message()}")# 应用场景
if __name__ == "__main__":pubsub = PubSubSystem()subscriber = NewsSubscriber()pubsub.subscribe("news", subscriber)news_message = NewsMessage("Breaking News!", "Important event occurred.")pubsub.publish(news_message)

在这个示例中,PubSubSystem扮演了发布者的角色,它维护了一个字典,键是主题名,值是订阅该主题的观察者列表。当有新的消息发布时,系统会查找订阅了该主题的所有订阅者,并调用它们的receive_message方法。NewsMessage是一个具体的消息类,NewsSubscriber是订阅者类,它定义了如何处理特定类型的消息。在主程序中,我们创建了一个发布/订阅系统实例,订阅了“news”主题,并发布了一个新闻消息。发布后,订阅了该主题的订阅者将会接收到并处理这条消息。

3.4 气象监测系统

在气象监测系统中,我们可以利用观察者模式来实现气象数据变化时自动通知订阅者(如气象分析软件、预警系统等)。下面是一个简化的Python实现:

import abc# 定义气象数据接口
class WeatherData(metaclass=abc.ABCMeta):@abc.abstractmethoddef get_temperature(self) -> float:pass@abc.abstractmethoddef get_humidity(self) -> float:pass@abc.abstractmethoddef get_pressure(self) -> float:pass# 定义观察者接口
class WeatherObserver(metaclass=abc.ABCMeta):@abc.abstractmethoddef update(self, weather_data: WeatherData):pass# 定义气象监测站(被观察者)
class WeatherStation:def __init__(self):self._observers = []self._weather_data = WeatherDataImpl()  # 假定WeatherDataImpl是实现了WeatherData接口的具体气象数据类def register_observer(self, observer: WeatherObserver):self._observers.append(observer)def remove_observer(self, observer: WeatherObserver):self._observers.remove(observer)def measurements_changed(self):for observer in self._observers:observer.update(self._weather_data)# 实现具体的观察者类
class WeatherAlertSystem(WeatherObserver):def update(self, weather_data: WeatherData):temp = weather_data.get_temperature()humidity = weather_data.get_humidity()pressure = weather_data.get_pressure()# 模拟检查天气状况并采取行动if temp > 35 or pressure < 950:print("Weather Alert System: Sending alerts due to extreme conditions!")# 应用场景
if __name__ == "__main__":station = WeatherStation()alert_system = WeatherAlertSystem()# 注册观察者station.register_observer(alert_system)# 模拟气象数据变化# (通常这部分由传感器或其他实时数据源提供,这里仅做演示)fake_update = WeatherDataImpl(temp=38, humidity=80, pressure=940)station._weather_data = fake_update  # 更改气象数据# 通知所有观察者数据已改变station.measurements_changed()

在这个例子中,WeatherStation是被观察者,它维护一个观察者列表,并在气象数据变化时调用measurements_changed方法通知所有观察者。WeatherObserver是观察者接口,具体观察者(如WeatherAlertSystem)实现了该接口以处理气象数据变化的事件。当气象监测站接收到新的气象数据时,所有已注册的观察者都会收到通知并执行相应的更新操作。

四、优缺点及适用情况

4.1 优缺点

  • 优点:
  1. 松耦合:观察者模式降低了主题(被观察者)和观察者之间的耦合度,它们只需要知道对方的接口即可,无需了解对方的具体实现细节。
  2. 灵活性:观察者可以在运行时动态添加或删除,增强了系统的灵活性和可扩展性。
  3. 复用性:一个被观察者可以同时拥有任意数量的观察者,方便了系统的模块化设计和重用。
  4. 广播通知:当被观察者状态改变时,能够一次性通知所有相关的观察者,简化了状态传播的过程。
  • 缺点:
  1. 开闭原则的挑战:为了支持新的观察者,有时需要修改被观察者的代码以添加新的通知方法。
  2. 效率问题:当观察者数量庞大且频繁更新时,通知所有观察者的操作可能成为性能瓶颈。
  3. 循环依赖:如果没有正确设计,可能会导致观察者和被观察者之间的循环依赖问题。
  4. 控制复杂度:随着系统规模增大,管理观察者列表和通知过程可能变得复杂,特别是在有多种类型的观察者和通知策略的情况下。
  5. 通知顺序无法保证:观察者模式并不保证通知的顺序,如果需要有序的通知,可能需要结合其他设计模式或机制来实现。

此外,Python标准库也提供了threading模块的EventConditionQueue等机制,用于线程间通信和事件通知,可以根据具体应用场景考虑是否采用这些内建工具替代传统的观察者模式。

4.2 实战中的注意事项

在实际应用观察者模式时,有几个关键点需要注意:

  • 避免循环依赖:确保不会出现观察者依赖于被观察者,又被被观察者依赖的情况,否则可能导致无限循环通知。

  • 处理好资源管理:尤其是当观察者数量巨大或者生命周期不确定时,要妥善处理资源释放,防止内存泄露等问题。

  • 控制通知频率:如果观察者数量众多并且频繁更新,可能会影响性能。可通过批处理、节流或截流等手段控制通知的频率和时机。

  • 明确边界和责任:清晰定义被观察者和观察者的职责范围,避免二者职责混淆,造成设计上的混乱。

五、高级特性和优化

在实际项目中,观察者模式可以通过一些优化手段来增强其表现力和实用性。例如:

5.1 异步通知

在高并发或多线程环境中,被观察者发出通知时,可能需要使用异步方式来避免阻塞。Python的asyncio库可以帮助我们将通知过程转换为非阻塞式任务,观察者则通过异步回调函数处理更新。

import asyncioclass AsyncStockPrice(Subject):async def notify_observers_async(self, price):tasks = [observer.update(self, price) for observer in self._observers]await asyncio.gather(*tasks)class AsyncPriceSubscriber(Observer):async def update(self, subject, price):print(f"异步股票价格更新:{subject.symbol}当前价格为{price:.2f}")# 异步示例
loop = asyncio.get_event_loop()
async_stock = AsyncStockPrice('AAPL')
async_subscriber1 = AsyncPriceSubscriber()
async_subscriber2 = AsyncPriceSubscriber()async_stock.attach(async_subscriber1)
async_stock.attach(async_subscriber2)loop.run_until_complete(async_stock.notify_observers_async(147.45))

5.2 弱引用

在长期运行的应用中,为了避免内存泄漏,可以使用弱引用(weakref)来持有观察者引用。这样,当没有其他强引用指向观察者时,系统会在适当的时候自动回收资源。

import weakrefclass WeakReferenceObserverPattern:def __init__(self):self._observers = weakref.WeakSet()def attach(self, observer):self._observers.add(observer)def detach(self, observer):try:self._observers.remove(observer)except KeyError:passdef notify_observers(self, *args, **kwargs):observers_copy = list(self._observers)for observer in observers_copy:observer.update(self, *args, **kwargs)

5.3 过滤器和中介者

在大型系统中,为了更精细地控制事件传递和处理流程,观察者模式可能结合过滤器模式或者中介者模式使用,以控制哪些观察者应该接收到什么样的更新。过滤器可以根据预设条件筛选出需要接收更新的观察者,而中介者则可以集中处理和转发事件,从而简化对象之间的交互。下面是一个简单示例,展示了如何在观察者模式中加入过滤器和中介者概念:

from abc import ABC, abstractmethod
from collections import defaultdictclass Filter(metaclass=ABC):@abstractmethoddef should_notify(self, observer, subject, change):passclass Mediator:def __init__(self):self._observers = defaultdict(list)self._filters = []def register_observer(self, observer, filter_=None):if filter_ is not None:self._filters.append(filter_)self._observers[observer].append(filter_)def unregister_observer(self, observer):del self._observers[observer]def notify_observers(self, subject, change):for observer, filter_ in self._observers.items():if filter_ is None or all(filter_.should_notify(observer, subject, change) for filter_ in filter_):observer.update(subject, change)class Subject:def __init__(self):self._mediator = Mediator()def attach(self, observer, filter_=None):self._mediator.register_observer(observer, filter_)def detach(self, observer):self._mediator.unregister_observer(observer)def notify(self, change):self._mediator.notify_observers(self, change)class ConcreteFilter(Filter):def should_notify(self, observer, subject, change):# 根据change内容决定是否通知观察者,这里只是一个简单的示例if change['type'] == 'important':return Truereturn Falseclass Observer(ABC):@abstractmethoddef update(self, subject, change):passclass ConcreteObserver(Observer):def update(self, subject, change):print(f"Observer: Received update: {change}")# 示例使用
subject = Subject()
observer1 = ConcreteObserver()
filter1 = ConcreteFilter()subject.attach(observer1, filter1)
subject.notify({'type': 'normal', 'data': 'Normal update'})
subject.notify({'type': 'important', 'data': 'Important update'})# 输出:
# Observer: Received update: {'type': 'important', 'data': 'Important update'}

在这个示例中,Mediator类替代了原有的直接通知观察者的方式,负责管理观察者列表和过滤器。ConcreteFilter是一个具体的过滤器实现,它定义了何时应该通知观察者。Subject类通过Mediator来注册和通知观察者,并且在通知时通过过滤器进行筛选。这样,只有满足过滤条件的观察者才会接收到通知。

六、总结

在Python中实现观察者模式可以帮助我们更好地组织复杂的业务逻辑,尤其是在处理涉及状态变更和多方响应的情况时。通过合理的应用和适当的优化,可以在多种场景下有效地降低模块之间的耦合度,实现系统内部的良好通信和协调工作。然而,在使用过程中也需要警惕过度使用导致的“扇出”问题(即一个对象的变化可能引发大量其他对象的反应),以及由此带来的性能影响和调试难度的增加。因此,在实际项目中需根据实际情况适度使用观察者模式,并结合其他设计模式来优化整体架构。
在这里插入图片描述


关注gzh不灵兔,Python学习不迷路,关注后后台私信,可进wx交流群,进群暗号【人生苦短】~~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1409847.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Linux(ubuntu)—— 用户管理user 用户组group

一、用户 1.1、查看所有用户 cat /etc/passwd 1.2、新增用户 useradd 命令&#xff0c;我这里用的是2.4的命令。 然后&#xff0c;需要设置密码 passwd student 只有root用户才能用passwd命令设置其他用户的密码&#xff0c;普通用户只能够设置自己的密码 二、组 2.1查看…

【右一的开发日记】全导航,持续更新...

文章目录 &#x1f4da;前端【跟课笔记】&#x1f407;核心技术&#x1f407;高级技术 &#x1f4da;捣鼓捣鼓&#x1f407;小小案例&#x1f407;喵喵大王立大功&#x1f407;TED自用学习辅助网站&#x1f407;世界top2000计算机科学家可视化大屏&#x1f407;基于CBDB的唐代历…

中间件之异步通讯组件RabbitMQ入门

一、概述 微服务一旦拆分&#xff0c;必然涉及到服务之间的相互调用&#xff0c;目前我们服务之间调用采用的都是基于OpenFeign的调用。这种调用中&#xff0c;调用者发起请求后需要等待服务提供者执行业务返回结果后&#xff0c;才能继续执行后面的业务。也就是说调用者在调用…

HTTP/1.1、HTTP/2、HTTP/3 的演变

HTTP/1.1、HTTP/2、HTTP/3 的演变 HTTP/1.1 相比 HTTP/1.0 提高了什么性能&#xff1f;HTTP/2 做了什么优化&#xff1f;HTTP/3 做了哪些优化&#xff1f; HTTP/1.1 相比 HTTP/1.0 提高了什么性能&#xff1f; HTTP/1.1 相比 HTTP/1.0 性能上的改进&#xff1a; 使用长连接的…

分拣机器人也这么卷了吗?!

导语 大家好&#xff0c;我是智能仓储物流技术研习社的社长&#xff0c;老K。专注分享智能仓储物流技术、智能制造等内容。 新书《智能物流系统构成与技术实践》 智能制造-话题精读 1、西门子、ABB、汇川&#xff1a;2024中国工业数字化自动化50强 2、完整拆解&#xff1a;智能…

4月20日,杭州Sui Meetup活动回顾

4 月 20 日在风景如画的杭州&#xff0c;「TinTin DESTINATION MOON」成功举办。此次活动深入探讨了 Sui 生态系统的演进及未来机遇&#xff0c;包括 Sui 上的资产管理协议 Mole、全链引擎 Obelisk Engine 以及 Generator 的开发范式等热点话题&#xff0c;行业专家提供了深刻见…

基于Spring Boot的校园闲置物品交易网站设计与实现

基于Spring Boot的校园闲置物品交易网站设计与实现 开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/idea 系统部分展示 系统功能界面图&#xff0c;在系统首页可以查看…

修改 Windows 服务器远程端口,以阿里云服务器 ECS 为例

一、WinR - mstsc.exe 登录远程服务器 二、WinR - regedit.exe 打开注册表 三、打开注册表 tcp 路径&#xff1a; 计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TerminalServer\Wds\rdpwd\Tds\tcp 双击右侧 PortNumber 子健&#xff0c;勾选十进制&a…

基于SpringBoot的私人健身与教练预约管理系统设计与实现

一、引言 私人健身与教练预约管理系统&#xff0c;可以摆脱传统手写记录的管理模式。利用计算机系统&#xff0c;进行用户信息、管理员信息的管理&#xff0c;其中包含首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;教练管理&#xff0c;健身项目管理&#xff0c;项…

GitLab服务器的搭建

GitLab服务器的搭建 为公司搭建一台代码托管服务器 服务器规格&#xff1a;2vCPUs4GiB20G 操作系统&#xff1a;RockyLinux8.8 下载软件 gitlab官网&#xff1a;http://about.gitlab.com 在官网下载比较麻烦&#xff0c;推荐从《清华大学开源软件镜像站》下载 清华大学开…

微服务保护和分布式事务(Sentinel、Seata)笔记

一、雪崩问题的解决的服务保护技术了解 二、Sentinel 2.1Sentinel入门 1.Sentinel的安装 &#xff08;1&#xff09;下载Sentinel的tar安装包先 &#xff08;2&#xff09;将jar包放在任意非中文、不包含特殊字符的目录下&#xff0c;重命名为 sentinel-dashboard.jar &…

File contains parsing errors: file:///etc/yum.repos.d/nginx.repo报错解决,文件配置出现问题

执行yum指令出现以下错误&#xff1a; 解决方案&#xff1a;yum的配置文件出现问题&#xff0c; 先删除yum.repos.d目录下所有文件 rm -f /etc/yum.repos.d/* 然后重新下载阿里的资源 wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.…

C#窗体控件DataGridView

目录 简介 基本框架 案例 案例1,往DataGridView中添加新列。 案例2&#xff0c;使用列名删除DataGridView中的某一列。 案例3&#xff0c;人手选中某一列&#xff0c;然后进行删除。 案例4&#xff0c;添加新的一行。 案例5&#xff0c;删除选中行。 案例6&#xff0c…

springboot 自动配置源码解读

SpringBootApplication 作用 SpringBootConfiguration&#xff1a;主启动类可以当做配置类使用&#xff0c;比如注入Bean等。ComponentScan&#xff1a;包扫描注解。EnableAutoConfiguration(重要)&#xff1a;开启自动配置。 EnableAutoConfiguration AutoConfigurationPackag…

基于simulink的电弧炉模型建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 基于simulink的电弧炉模型建模与仿真&#xff0c;输出电弧炉模型的电压曲线和电流曲线以及U-I分布图。 2.系统仿真结果 3.核心程序与模型 版本&#xff1a;MATLAB2022a 53 …

unity制作app(2)--主界面

1.先跳转过来&#xff0c;做一个空壳&#xff01;新增场景main为4号场景&#xff01; 2.登录成功跳转到四号场景&#xff01; 2.在main场景中新建canvas&#xff0c;不同的状态计划用不同的panel来设计&#xff01; 增加canvas和底图image 3.突然输不出来中文了&#xff0c;浪…

java:错误:不支持发行版本

你在运行的时候是否遇见过这样的问题: 有时候新建一个Java项目后&#xff0c;运行起来就会提示这样的错误。主要原因是因为项目使用的Java版本和安装的Java版本不符合 &#xff0c;在这里总结一下解决方法: 首先点击file的project 把Java编译器也设置成 一样的版本 即可解决问…

a_bogus逆向分析

a_bogus逆向分析 前言log插桩步骤一分析步骤二分析 前言 最新版本的a_bogus生成步骤大致分为以下4步&#xff1a;步骤操作一根据请求的params、data、useragent以及环境参数生成四个数组二通过一些规则把步骤一生成的四个数组组合成一个大数组三通过一些随机数生成一个乱码字符…

如何使用Go语言进行基准测试(benchmark)?

文章目录 一、基准测试的基本概念二、编写基准测试函数三、运行基准测试四、优化代码性能五、注意事项总结 在Go语言中&#xff0c;基准测试&#xff08;benchmark&#xff09;是一种评估代码性能的有效方式。通过基准测试&#xff0c;我们可以测量代码执行的时间、内存使用情况…

【MATLAB画图】如何绘制图像坐标系

首先我们需要图像坐标轴的原点在左上角&#xff1a; set(gca,ydir,reverse,xaxislocation,top); 然后我们需要坐标轴上加上箭头 quiver(0, 0, 0, 520); % 在(x1, y1)处绘制一个箭头&#xff0c;其方向和长度由(dx, dy)确定 quiver(0, 0, 700, 0); % 在(x1, y1)处绘制一个箭头…