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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【如何训练一个中译英翻译器】LSTM机器翻译模型部署之ncnn(python)(五)

系列文章 【如何训练一个中译英翻译器】LSTM机器翻译seq2seq字符编码(一) 【如何训练一个中译英翻译器】LSTM机器翻译模型训练与保存(二) 【如何训练一个中译英翻译器】LSTM机器翻译模型部署(三) 【如何训练…

【优选算法题练习】day8

文章目录 一、974. 和可被 K 整除的子数组1.题目简介2.解题思路3.代码4.运行结果 二、525. 连续数组1.题目简介2.解题思路3.代码4.运行结果 三、560. 和为 K 的子数组1.题目简介2.解题思路3.代码4.运行结果 总结 一、974. 和可被 K 整除的子数组 1.题目简介 974. 和可被 K 整…

React之组件的分类、使用,事件对象,this指向问题,修改状态以及受控组件与非受控组件

React之组件的介绍、创建与使用,事件对象,this指向问题,修改状态以及受控组件与非受控组件 一、组件基本介绍二、组件创建2.1 函数组件2.2 类组件 三、将组件提取到单独的js文件中四、有状态组件和无状态组件五、类组件的状态六、事件处理6.1 注册事件6.2 事件对象6.3 this指向…

【设计模式】单例设计模式详解(包含并发、JVM)

文章目录 1、背景2、单例模式3、代码实现1、第一种实现(饿汉式)为什么属性都是static的?2、第二种实现(懒汉式,线程不安全)3、第三种实现(懒汉式,线程安全)4、第四种实现…

day38-Mobile Tab Navigation(手机tab栏导航切换)

50 天学习 50 个项目 - HTMLCSS and JavaScript day38-Mobile Tab Navigation&#xff08;手机tab栏导航切换&#xff09; 效果 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"…

3ds MAX 洗菜池

在家居中我们显然离不开这个对吧 首先绘制一个长方体作为基础 注意设置长宽高的网格大小&#xff0c;方便后续调整 俯视图网格线如下&#xff1a; 长方形变换为可编辑网络&#xff0c;并在【多边形】界面选择底面的所有多边形&#xff0c;按delete删除&#xff0c;形成一个壳体…

Github上方导航栏介绍

Code Watch&#xff1a;相当于关注&#xff0c;到时候这个项目又有什么操作&#xff0c;就会以通知的形式提醒你。 Fork&#xff1a;也就是把这个项目拉到你的仓库里&#xff0c;之后你可以对该代码进行修改&#xff0c;之后你可以发起Pull Request&#xff0c;简称PR&#xf…

vulnhub靶场之CengBox3

1.信息收集 输入命令&#xff1a;netdiscover -i eth0 -r 192.168.239.0 &#xff0c;发现181机器存活 输入命令nmap -p- -sV -O -Pn -A 192.168.239.181 &#xff0c;进行端口探测&#xff0c;发现存在22、80、443端口&#xff0c;还发现存在域名ceng-company.vm。 将域名c…

了解Unity编辑器之组件篇Tilemap(五)

Tilemap&#xff1a;用于创建和编辑2D网格地图的工具。Tilemap的主要作用是简化2D游戏中地图的创建、编辑和渲染过程。以下是一些Tilemap的主要用途&#xff1a; 2D地图绘制&#xff1a;Tilemap提供了一个可视化的编辑器界面&#xff0c;可以快速绘制2D地图&#xff0c;例如迷…

docker版jxTMS使用指南:新建用户并授权

本文讲解4.4版jxTMS中如何新建用户并授权&#xff0c;整个系列的文章请查看&#xff1a;[docker版jxTMS使用指南&#xff1a;docker版jxTMS使用指南&#xff1a;4.4版升级内容 docker版本的使用&#xff0c;请查看&#xff1a;docker版jxTMS使用指南 4.0版jxTMS的说明&#x…

python实现逻辑回归-清风数学建模-二分类水果数据

所用数据 &#x1f449;&#x1f449;&#x1f449;二分类水果数据 1.数据预处理 可以看到有4个特征&#xff0c;2种分类结果&#xff0c;最后4个没有分类结果的数据是拿来预测的 # 1. 数据预处理 import pandas as pd df pd.read_excel(oridata/二分类水果数据.xlsx,use…

开源大模型LLaMA 2会扮演类似Android的角色么?

在AI大模型没有商业模式&#xff1f;等文章中&#xff0c;我多次表达过这样一个观点&#xff1a;不要把大模型的未来应用方式比喻成公有云&#xff0c;大模型最终会是云端操作系统的核心&#xff08;新通用计算平台&#xff09;&#xff0c;而它的落地形式会很像过去的沃森&…

【C++】开源:Linux端ALSA音频处理库

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍Linux端ALSA音频处理库。 无专精则不能成&#xff0c;无涉猎则不能通。。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c…

Python增删改查小练习

目录 1. List操作-增加 2. List操作-查询 3. List操作-修改 4. List操作-删除 资料获取方法 1. List操作-增加 List Append(“xx”) 插入到列表尾部 Insert(x,xx) 在指定的位置插入 Extend 将列表的元素分开,插入到之前列表的尾部 小练习: 把一个字符串”abcdefg…

ssh打开远程vscode

如果想要远程打开其他终端的vscode&#xff0c;首先要知道远程终端的ip地址和用户名称以及用户密码 1、打开本地vscode 2、点击左下角蓝色区域 3、页面上部出现如下图&#xff0c;点击ssh&#xff0c;我这里已经连接&#xff0c;所以是connect to host 4、选择Add New SSH Host…

线程池几个核心参数说明

线程池几个核心参数 corePoolSize&#xff1a;核心线程数量大小。maximumPoolSize&#xff1a;线程池最大容纳线程数。keepAliveTime&#xff1a;线程空闲后的存活时长。TimeUnit&#xff1a;单位时间。BlockingQueue&#xff1a;缓存异步任务的队列。 ThreadFactory &#xff…

appium中toast识别

目录 一、什么是Toast&#xff1f; 二、环境前提 三、修改配置 四、安装驱动 五、常见报错及解决方案 1、cnpm 不识别&#xff0c;提示不是内部或外部命令 2、npm 也不识别 3、报错 六、代码节选 一、什么是Toast&#xff1f; Android中的Toast是一种简易的消息提示框…

比selenium体验更好的ui自动化测试工具: cypress介绍

话说 Cypress is a next generation front end testing tool built for the modern web. And Cypress can test anything that runs in a browser.Cypress consists of a free, open source, locally installed Test Runner and a Dashboard Service for recording your tests.…

AutoSAR系列讲解(实践篇)9.1-协议数据单元PDU

本章主要是讲解通信(不包括诊断和标定的纯通信),同样是主要以CAN来讲解。由于通信大家其实用的基本上是其最基础的功能,所以本章的实验主要就是教大家如何配置基础通信,但是高级一点的功能,博主也会在前面这几节给大家讲到,用不到的同学仅作了解就行。同样,忘了通信是怎…

day44-Spring_AOP

0目录 1.2.3 1.Spring_AOP 实体类&#xff1a; Mapper接口&#xff1a; Service和实现类&#xff1a; 测试1&#xff1a; 运行后&#xff1a; 测试2&#xff1a;无此型号时 测试3&#xff1a;库存不足时 解决方案1&#xff1a;事务声明管理器 测试&#xff1a…