单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。

比如,某个服务器程序的配置信息存放在一个文件中,客户端通过一个 AppConfig 的类来读取配置文件的信息。如果在程序运行期间,有很多地方都需要使用配置文件的内容,也就是说,很多地方都需要创建 AppConfig 对象的实例,这就导致系统中存在多个 AppConfig 的实例对象,而这样会严重浪费内存资源,尤其是在配置文件内容很多的情况下。事实上,类似 AppConfig 这样的类,我们希望在程序运行期间只存在一个实例对象。

在 Python 中,我们可以用多种方法来实现单例模式

1.使用装饰器

def Singleton(cls):

_instance = {}

def _singleton(*args, **kwargs):

if cls not in _instance:

_instance[cls] = cls(*args, **kwargs)

return _instance[cls]

return _singleton

@Singleton

class A(object):

a = 1

def __init__(self, x=0):

self.x = x

a1 = A(2)

a2 = A(3)

解释一下这个装饰器:单例模式的主要目的就是确保某一个类最多只能有一个实例存在,换句话说某一个类只能和它的一个实例有联系,所以字典这种键值对型的容器非常适合单例模式这种情况。如果某个类不在字典里,那么在字典里创建一个键为某个类(cls),值为该类创建的实例(cls(*args, **kwargs))这样的一个键值对。如果某个类已经在字典里,那么说明这个类在之前已经创建过实例了,按照单例模式一个类最多只能有一个实例的思想,那么直接返回该类的实例

2.基于__new__方法实现

当我们实现单例时,为了保证线程安全需要在内部加入锁

我们知道,当我们实例化一个对象时,是先执行了类的__new__方法(我们没写时,默认调用object.new),实例化对象;然后再执行类的__init__方法,对这个对象进行初始化,所有我们可以基于这个,实现单例模式

import threading

class Singleton(object):

_instance_lock = threading.Lock()

def __init__(self):

pass

def __new__(cls, *args, **kwargs):

if not hasattr(Singleton, "_instance"):

with Singleton._instance_lock:

if not hasattr(Singleton, "_instance"):

Singleton._instance = object.__new__(cls)

return Singleton._instance

obj1 = Singleton()

obj2 = Singleton()

print(obj1,obj2)

def task(arg):

obj = Singleton()

print(obj)

for i in range(10):

t = threading.Thread(target=task,args=[i,])

t.start()

简单一点,没有加锁的方式:

#使用__new__方法在创造实例时进行干预,达到实现单例模式的目的

#这里使用了_instance属性来存放实例

class Singleton: #一个通用的单例超类,其他类继承即可(也可通过装饰器实现)

def __new__(cls, *args, **kw):

if not hasattr(cls, '_instance'):

cls._instance = object.__new__(cls)

return cls._instance

class SingleSpam(Singleton):

def __init__(self, s):

self.s = s

def __str__(self):

return self.s

s1 = SingleSpam('spam')

print(id(s1), s1)

s2 = SingleSpam('spa')

print(id(s2), s2)

介绍一下__new__:

class A:

pass

class B(A):

def __new__(cls):

print("__new__方法被执行")

return super().__new__(cls)

def __init__(self):

print("__init__方法被执行")

b = B()

# __new__方法被执行

# __init__方法被执行

我们比较两个方法的参数,可以发现__new__方法是传入类(cls),而__init__方法传入类的实例化对象(self),而有意思的是,__new__方法返回的值就是一个实例化对象(如果__new__方法返回None,则__init__方法不会被执行,并且返回值只能调用父类中的__new__方法,而不能调用毫无关系的类的__new__方法)。我们可以这么理解它们之间的关系,__new__是开辟疆域的大将军,而__init__是在这片疆域上辛勤劳作的小老百姓,只有__new__执行完后,开辟好疆域后,__init__才能工作。

用python实现单例模式_Python单例模式的两种实现方式相关推荐

  1. 多线程python实现方式_python多线程的两种实现方式(代码教程)

    本篇文章给大家带来的内容是关于python多线程的两种实现方式(代码教程),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 线程是轻量级的进程,进程中可划分出多个线程,线程可独立的调度 ...

  2. python请输入_python中的三种输入方式

    python中的三种输入方式 python2.X python2.x中以下三个函数都支持: raw_input() input() sys.stdin.readline() raw_input( )将 ...

  3. 【无标题】单例模式的两种创建方式:饿汉式和懒汉式

    这里写自定义目录标题 单例模式的两种创建方式:饿汉式和懒汉式 欢迎使用Markdown编辑器 新的改变 功能快捷键 合理的创建标题,有助于目录的生成 如何改变文本的样式 插入链接与图片 如何插入一段漂 ...

  4. python定义字符串变量有两种常用方式_Python 1基础语法二(标识符、关键字、变量和字符串)...

    一.标识符 标识符就是程序员自己命名的变量名.名字需要有见名知义的效果,不要随意起名 :比如 a=1 a是个变量,a这个变量名属于标识符 1 company = '小米 2 employeeNum = ...

  5. python字典对象的方法返回字典的值列表_python对象转字典的两种实现方式示例

    本文实例讲述了python对象转字典的两种实现方式.分享给大家供大家参考,具体如下: 一. 方便但不完美的__dict__ 对象转字典用到的方法为__dict__. 比如对象对象a的属性a.name= ...

  6. 简单介绍python连接telnet和ssh的两种方式

    本文主要介绍了python连接telnet和ssh的两种方式,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 Telnet 连接方式 #!/usr/bin/env p ...

  7. python 读取wav 音频文件的两种方式

    python 中,常用的有两种可以读取wav音频格式的方法,如下所示: 1 import scipy 2 from scipy.io import wavfile 3 4 import soundfi ...

  8. python repair修复功能_详解Python修复遥感影像条带的两种方式

    GDAL修复Landsat ETM+影像条带 Landsat7 ETM+卫星影像由于卫星传感器故障,导致此后获取的影像出现了条带.如下图所示, 影像中均匀的布满条带. 使用GDAL修复影像条带的代码如 ...

  9. python支持的编程方式包括,python的两种编程方式是什么

    一.交互式编程 什么是交互式编程,就是在命令行中输入python 命令即可启动交互式编程,提示窗口如下: 而且还用了Python3的print方法打印出一串字符串. 二.脚本式编程 通过脚本参数调用解 ...

  10. Python操作Neo4j图数据库的两种方式

    Python操作Neo4j图数据库的两种方式 前言 1. 用neo4j模块执行CQL ( cypher ) 语句 2. 用py2neo模块通过操作python变量,达到操作neo4j的目的 3. 用p ...

最新文章

  1. c语言语系的命名风格和java系命名风格
  2. 围巾都这么黑科技了,是我见识少了
  3. 成功解决FileNotFoundError: [WinError 2] 系统找不到指定的文件。
  4. MySQl的一些基本知识(1)
  5. 明日之后怎么跳过实名认证_明日之后宝箱达人活动怎么玩 明日之后宝箱达人可以开箱多少次...
  6. 一个高并发的测试websocket脚本
  7. tensorrt安装_基于TensorRT的BERT推断加速与服务部署
  8. ASA8.4端口映射篇
  9. Android 震动
  10. 求字符串中对称的子字符串的最大长度
  11. Cogs 647. [Youdao2010] 有道搜索框(Trie树)
  12. 中国氮化镓(GaN)行业“十四五”前景预测及投资风险预测报告2021年版
  13. usbcan、can分析仪的产品特点和功能特点
  14. Discuz 手动添加 markdown 代码支持教程!
  15. html代码 层次选择器,CSS样式类的实例代码(导航栏、分页、层级选择器)
  16. css flex实现经典的三栏布局
  17. APS究竟是什么系统呢?看完文章你就知道了
  18. 《大唐卫星网络电视》
  19. 中国马铃薯全粉产业经营策略与销售渠道研究报告(2022-2027年)
  20. python基础语法25_Python基础语法习题参考(0-9关)

热门文章

  1. 【图论训练】最小拓扑序
  2. 从IT的角度思考BIM(二):模式与框架
  3. SPOJ AMR12B 720
  4. Python 调试:pdb
  5. .net无刷新验证码
  6. javascript 常用的一些事件和应用
  7. 用C#生成随机中文汉字验证码
  8. php 调用模板,调用模板
  9. kafka监听topic消费_Kafka消费者-从Kafka读取数据
  10. 今晚直播 | Oracle技术加油站:快速处理紧急性能问题的工具与经验