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

Python单例模式介绍、使用

 一、单例模式介绍

  • 概念:单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供访问该实例的全局访问点。

  • 功能:单例模式的主要功能是确保在应用程序中只有一个实例存在。

  • 优势:

    1. 节省系统资源:由于只有一个实例存在,因此系统的资源占用会比较小。
    2. 更好的控制全局变量:单例模式可以有效控制全局变量的使用方式,从而更好地维护程序的可维护性和可扩展性。
    3. 更好的共享资源:由于只有一个实例存在,因此可以更好地共享资源。
  • 劣势:

    1. 单例模式可能会引起代码耦合:由于单例模式只能创建一个实例,因此在程序中可能会出现过度依赖单例模式的情况,这会导致代码的耦合度变高。
    2. 单例模式可能会导致性能问题:如果单例模式的实例化过程比较复杂,可能会导致性能问题。
  • 应用场景:

    1. 日志处理器:在应用程序中,只需要一个日志处理器来记录所有的日志信息。
    2. 数据库连接池:在应用程序中,只需要一个数据库连接池来管理所有的数据库连接。
    3. 全局配置信息:在应用程序中,只需要一个配置信息实例来管理所有的全局配置信息。

总之,单例模式适用于那些需要确保在应用程序中只有一个实例存在的情况,同时需要节省系统资源并且更好地控制全局变量。但同时,我们也需要注意单例模式可能引起的代码耦合和性能问题。

二、单例模实现原理

实现步骤

Python单例模式的实现原理基本与其编语言的单例模式实现原理相同。实现步骤如下:

  1. 定义一个类变量,用于存储单例实例
  2. 在初始化方法中,检查类变量是否已经被赋值。如果没有,则创建一个新的实例,并将其赋值给类变量。如果已经有一个实例在类变量中,则返回该实例
  3. 提供一个静态方法来返回类变量中保存的单例实例

具体来说,单例模式的实现步骤如下:

class Singleton:__instance = Nonedef __init__(self):if Singleton.__instance is None:Singleton.__instance = selfelse:raise Exception("Singleton class instantiated more than once")@staticmethoddef get_instance():if not Singleton.__instance:Singleton()return Singleton.__instance

在上面的代码中,我们定义了一个类变量__instance来保存单例实例,我们通过构造函数__init__来检查该实例是否已经存在。如果不存在,则创建一个新的实例。如果已经存在,则抛出一个异常,防止创建多个实例。

我们还实现了一个静态方法get_instance,该方法返回类变量__instance保存的单例实例。在调用该方法时,我们首先检查类变量__instance是否存在,如果不存在,则创建一个新的实例。否则,我们只返回保存在类变量__instance中的实例。

以下是使用上述代码的示例:

s1 = Singleton.get_instance()
s2 = Singleton.get_instance()assert s1 == s2     # s1 and s2 are equal

由于Singleton模式确保一个类只有一个实例,因此s1和s2应该是相等的。由于它们都是同一个实例,所以它们应该返回True。

静态方法介绍

@staticmethod是Python中的一个装饰器(decorator),它表明该方法是一个静态方法。静态方法是一个与类相关的函数,不依赖于类中的任何实例,因此静态方法可以在不创建类的实例的情况下调用。静态方法可以在类中使用,也可以在类外部使用。

静态方法使用@staticmethod装饰器来声明。例如:

class MyClass:@staticmethoddef my_static_method():print("This is a static method")

在上面的代码中,我们定义了一个MyClass类,并使用@staticmethod装饰器来声明静态方法my_static_method()。在类的实例中,我们可以通过以下方式调用该方法:

my_instance = MyClass()
my_instance.my_static_method()

或者,我们也可以在类外部直接调用该方法:

MyClass.my_static_method()

请注意,与其他编程语言不同,Python中的静态方法可以访问类变量,但不能访问实例变量。

@staticmethod是一个装饰器(decorator),用于声明一个静态方法。静态方法是属于类的方法,而不是属于类的实例的方法。使用@staticmethod装饰器可以使方法不依赖于任何类实例而被调用。

静态方法可以在不需要实例化类的情况下进行调用。在静态方法中,不能访问类中的实例变量或实例方法。如果需要访问类中的属性或方法,则应该使用@classmethod装饰器声明一个类方法。

使用静态方法的主要目的是将方法与类关联,而不是与类的实例关联。因此,在需要在类的实例之间共享方法时,静态方法非常有用。

以下是一个使用@staticmethod装饰器的例子:

class MyClass:@staticmethoddef my_static_method():print("This is a static method")

在上面的代码中,我们定义了一个名为MyClass的类,并使用@staticmethod装饰器声明了一个名为my_static_method()的静态方法。我们可以在类的实例之间共享该方法,或者在类外部直接调用该方法。

my_instance = MyClass()
my_instance.my_static_method()MyClass.my_static_method()

输出结果:

This is a static method
This is a static method

类的实例之间共享方法

在Python中,类的实例之间可以共享方法。这是因为Python中的方法是在类的级别定义的,而不是在实例级别定义的。因此,所有该类的实例都共享相同的方法。

以下是一个示例,其中两个类的实例共享一个简单的方法:

class MyClass:@staticmethoddef my_static_method():print("This is a static method")instance_1 = MyClass()
instance_2 = MyClass()instance_1.my_static_method()
instance_2.my_static_method()

输出结果:

This is a static method
This is a static method

在上面的代码中,我们定义了一个名为MyClass的类,并使用@staticmethod装饰器声明了一个名为my_static_method()的静态方法。我们创建了两个MyClass的实例,并在它们之间共享该方法。

当我们在这两个实例上调用这个方法时,我们会发现它们都打印出了相同的消息,证明了这两个实例之间的方法是共享的。

三、示例

实现全局配置功能

单例模式可以用于实现全局配置信息功能,确保应用程序中的所有模块都使用相同的配置信息,避免冲突和不一致性。

以下是一个简单的示例,演示如何使用单例模式实现全局配置信息功能:

class Config:__instance = None__config_data = {'key1': 'value1', 'key2': 'value2'}def __new__(cls):if cls.__instance is None:cls.__instance = super().__new__(cls)return cls.__instancedef get_config_value(self, key):return self.__config_data.get(key)def set_config_value(self, key, value):self.__config_data[key] = valueconfig1 = Config()
config2 = Config()# Set a new config value using config1
config1.set_config_value('key1', 'new_value1')# Get the config value using config2
print(config2.get_config_value('key1'))

在上面的代码中,我们定义了一个名为 Config 的单例类,并在这个类中定义了一个静态私有变量 __instance,以确保该类的实例只被创建一次。我们还定义了一个名为 __config_data 的私有字典变量,用于存储全局配置信息。

在类定义中,我们使用 __new__() 方法来返回单例实例。如果该类已经有了一个实例,那么以后再次调用 __new__() 方法就会返回这个实例,而不是创建一个新的实例。

我们还定义了两个实例方法,get_config_value()set_config_value(),用于获取和设置配置信息。

在这个示例中,我们创建了两个 Config 类的实例 config1config2。我们先使用 config1key1 进行了设置,然后使用 config2 来获取 key1 的值。我们发现,尽管我们在 config1 对象上进行了更改,但是 config2 对象获取到的值仍然是 value1,证明了这两个实例共享相同的全局配置信息。

实现记录日志功能

假设我们有一个需要记录日志的应用程序,我们希望在整个应用程序中只有一个日志处理器实例,因为多个日志处理器实例会占用系统资源,导致程序运行缓慢。这时我们可以使用Python单例模式来确保应用程序中只有一个日志处理器实例。

具体实现如下:

class Logger:instance = Nonedef __init__(self):if not Logger.instance:Logger.instance = selfelse:self.__dict__ = Logger.instance.__dict__def log(self, message):# 日志记录逻辑pass

在上面的代码中,我们使用了一个类变量instance来保存Singleton类的唯一实例。在每次创建Singleton对象时,我们首先检查类变量是否已经被赋值。如果没有,则创建一个新的实例,并将其赋值给类变量。如果已经有一个实例在类变量instance中,则返回该实例。这样,我们就保证了整个应用程序中只有一个Logger实例存在。

使用上述代码的例子:

logger1 = Logger()
logger2 = Logger()assert logger1 == logger2

由于Singleton模式确保一个类只有一个实例,因此logger1和logger2应该是相等的。由于它们都是同一个实例,所以它们应该返回True。

class MyClass:@staticmethod # @staticmethod装饰器声明了一个名为my_static_method()的静态方法def my_static_method():print("This is a static method")instance_1 = MyClass()
instance_2 = MyClass()# 实例之间共享方法
# 实例1,2 共享了MyClass()类的my_static_method()方法
instance_1.my_static_method()
instance_2.my_static_method()class Singleton:__instance = Nonedef __init__(self):if Singleton.__instance is None:Singleton.__instance = selfelse:raise Exception("Singleton class instantiated more than once")@staticmethoddef get_instance():if not Singleton.__instance:Singleton()return Singleton.__instances1 = Singleton.get_instance()
s2 = Singleton.get_instance()assert s1 == s2     # s1 and s2 are equalclass Logger:instance = Nonedef __init__(self):if not Logger.instance:Logger.instance = selfelse:self.__dict__ = Logger.instance.__dict__def log(self, message):# 日志记录逻辑# print(message)return messagelogger1 = Logger()
logger2 = Logger()
print(logger1.log("log1"))print(logger2.log("log2"))# assert logger1 == logger2#********************* python 单例模式实现全局配置信息功能
class Config:__instance = None__config_data = {'key1': 'value1', 'key2': 'value2'}def __new__(cls):if cls.__instance is None:cls.__instance = super().__new__(cls)return cls.__instancedef get_config_value(self, key):return self.__config_data.get(key)def set_config_value(self, key, value):self.__config_data[key] = valueconfig1 = Config()
config2 = Config()print(config2.get_config_value('key1'))# Set a new config value using config1
config1.set_config_value('key1', 'new_value1') # 设置已有信息
config1.set_config_value('key3', 'new_value3') # 新增信息# Get the config value using config2
print(config2.get_config_value('key1'))
print(config2.get_config_value('key2'))
print(config2.get_config_value('key3'))

运行结果:

This is a static method
This is a static method
log1
log2
value1
new_value1
value2
new_value3

相关文章:

Python单例模式介绍、使用

一、单例模式介绍 概念:单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供访问该实例的全局访问点。 功能:单例模式的主要功能是确保在应用程序中只有一个实例存在。 优势: 节省系统资源:由…...

1334179-85-9,BTTAA,是各种化学生物学实验中生物偶联所需

资料编辑|陕西新研博美生物科技有限公司小编MISSwu​ BTTAA试剂 | 基础知识概述(部分): 中文名称:2-[4-({双[(1-叔丁基-1H-1,2,3-三唑-4-基)甲基]氨基}甲基)-1H-1,2,3-三唑-1-基]乙酸 英文名称:BTTAA CAS号:1334179-8…...

Linux系统中的SQL语句

本节主要学习,SQL语句的语句类型,数据库操作,数据表操作,和数据操作等。 文章目录 一、SQL语句类型 DDL DML DCL DQL 二、数据库操作 1.查看 2.创建 默认字符集 指定字符集 3.进入 4.删除 5.更改 库名称 字符集 6…...

力扣27 26 283 844 977 移除数组

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。 元素的顺序可以改变。你不需要考虑数组中超出新长度后面的…...

【沐风老师】3DMAX自动材质插件使用方法教程

3DMAX自动材质插件使用方法教程 3DMAX自动材质工具用于在将纹理加载到3dsax中时快速创建简单的材质,并具有一些很酷的材质功能。 这个插件可以根据真正制造商的纹理(通常比例为2:1)快速创建简单的木材材质,并根据板材的长度自动对…...

让你 React 组件水平暴增的 5 个技巧

目录 透传 className、style 通过 forwardRef 暴露一些方法 useCallback、useMemo 用 Context 来跨组件传递值 React.Children、React.cloneElement 总结 最近看了一些 Ant Design 的组件源码,学到一些很实用的技巧,这篇文章来分享一下。 首先&am…...

阿里云部署 ChatGLM2-6B 与 langchain+ChatGLM

1.ChatGLM2-6B 部署 更新系统 apt-get update 安装git apt-get install git-lfs git init git lfs install 克隆 ChatGLM2-6B 源码 git clone https://github.com/THUDM/ChatGLM2-6B.git 克隆 chatglm2-6b 模型 #进入目录 cd ChatGLM2-6B #创建目录 mkdir model #进入目录 cd m…...

F12开发者工具的简单应用

目录 elements 元素 1、元素的定位和修改 2、UI自动化应用 console 控制台 sources 源代码 network 网络 1、定位问题 2、接口测试 3、弱网测试 performance 性能 memory 存储 application 应用 recorder 记录器 界面展示如下(设置中可以切换中英文&am…...

【 Python 全栈开发 - 人工智能篇 - 45 】决策树与随机森林

文章目录 一、概念与原理1.1 决策树1.1.1 概念1.1.2 原理特征选择分割方法 1.1.3 优点与缺点1.1.4 Python常用决策树算法 1.2 随机森林1.2.1 概念1.2.2 原理1.2.3 优点与缺点1.2.4 Python常用随机森林算法 1.3 决策树与随机森林的比较1.3.1 相同之处1.3.2 不同之处 二、决策树算…...

SpringBoot集成kafka全面实战

本文是SpringBootKafka的实战讲解,如果对kafka的架构原理还不了解的读者,建议先看一下《大白话kafka架构原理》、《秒懂kafka HA(高可用)》两篇文章。 一、生产者实践 普通生产者 带回调的生产者 自定义分区器 kafka事务提交…...

新建Git仓库,将本地文件上传至仓库

1、新建仓库,勾选初始化仓库 2、复制仓库链接 3、打开本地文件目录 右键选择 Git Bash Here 打开命令窗口 4、依次按照下面的步骤(*如果报错,看原目录下是否存在 .git 需要删除) // 生成git文件 git init // 把文件加入暂存区 g…...

算法练习——力扣随笔【LeetCode】【C++】

文章目录 LeetCode 练习随笔力扣上的题目和 OJ题目相比不同之处?定义问题排序问题统计问题其他 LeetCode 练习随笔 做题环境 C 中等题很值,收获挺多的 不会的题看题解,一道题卡1 h ,多来几道,时间上耗不起。 力扣上的题…...

web服务器(Tomcat)

目录 一、web服务器 1. 常见web服务器 2. web服务器简介 二、 Apache Tomcat服务器 1. Tomcat服务器简介 2. Tomcat服务器基本使用 3. 启动tomcat常见问题 (1)启动tomcat控制台乱码 (2)启动tomcat闪退问题 (…...

测试方案、功能测试报告、性能测试报告

测试方案内容概要: 项目内容介绍,测试计划安排(人员时间),测试环境(系统配置)需求功能点(内容介绍,测试安排),重点难点场景,系统集成…...

【代码随想录day21】二叉搜索树的最近公共祖先

题目 思路 解题的关键是知道自顶向低递归遍历,第一次遇到root在p和q的区间中时,则root就是p和q的最近公共祖先节点。 递归法 # Definition for a binary tree node. # class TreeNode: # def __init__(self, x): # self.val x # …...

ssm文章发布管理系统java小说作品发表jsp源代码mysql

本项目为前几天收费帮学妹做的一个项目,Java EE JSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。 一、项目描述 ssm文章发布管理系统 系统有2权限:前台账…...

AXI协议之AXILite开发设计(二)

微信公众号上线,搜索公众号小灰灰的FPGA,关注可获取相关源码,定期更新有关FPGA的项目以及开源项目源码,包括但不限于各类检测芯片驱动、低速接口驱动、高速接口驱动、数据信号处理、图像处理以及AXI总线等 二、AXI-Lite关键代码分析 1、时钟与…...

Qgis二次开发-QgsMapTool地图交互工具详解

1.简介 QgsMapTool地图工具是用于操作地图画布的用户交互式工具。例如,地图平移和缩放功能被实现为地图工具。 QgsMapTool是抽象基类,以下是类的继承关系: 2.常用接口 virtual void canvasDoubleClickEvent (QgsMapMouseEvent *e)重写鼠标…...

MySQL基础(四)数据库备份

目录 前言 一、概述 1.数据备份的重要性 2.造成数据丢失的原因 二、备份类型 (一)、物理与逻辑角度 1.物理备份 2.逻辑备份 (二)、数据库备份策略角度 1.完整备份 2.增量备份 三、常见的备份方法 四、备份&#xff08…...

子类化QThread来实现多线程,moveToThread函数的作用

子类化QThread来实现多线程, QThread只有run函数是在新线程里的,其他所有函数都在QThread生成的线程里。正确启动线程的方法是调用QThread::start()来启动。 一、步骤 子类化 QThread;重写run,将耗时的事件放到此函数执行&#…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...

无法与IP建立连接,未能下载VSCode服务器

如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

掌握 HTTP 请求:理解 cURL GET 语法

cURL 是一个强大的命令行工具&#xff0c;用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中&#xff0c;cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关

在水泥厂的生产流程中&#xff0c;工业自动化网关起着至关重要的作用&#xff0c;尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关&#xff0c;为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多&#xff0c;其中不少设备采用Devicenet协议。Devicen…...

ubuntu22.04有线网络无法连接,图标也没了

今天突然无法有线网络无法连接任何设备&#xff0c;并且图标都没了 错误案例 往上一顿搜索&#xff0c;试了很多博客都不行&#xff0c;比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动&#xff0c;重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...