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

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

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

1.使用模块

可以参考自定义增删改查组件site对象,很明显的单利模式

其实,Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。如果我们真的想要一个单例类,可以考虑这样做:

# mysingleton.py
class My_Singleton(object):def foo(self):passmy_singleton = My_Singleton()

将上面的代码保存在文件 mysingleton.py 中,然后这样使用:

from mysingleton import my_singletonmy_singleton.foo()

2.使用 new

#Python学习交流QQ群:579817333
from django.test import TestCase# Create your tests here.
class Singleton:def __init__(self,name):self.name=namedef __new__(cls, *args, **kw):if not hasattr(cls, '_instance'):orig = super(Singleton, cls)cls._instance = orig.__new__(cls)return cls._instanceone = Singleton('aa')
two = Singleton('bb')
print(one.name)
print(one.name)two.a = 3
print(one.a)
# one和two完全相同,可以用id(), ==, is检测
print(id(one))
print(id(two))
print(one == two)
print(one is two)

加上锁

import time
import threading
class Singleton(object):_instance_lock = threading.Lock()def __init__(self):time.sleep(1)print(self)def __new__(cls, *args, **kwargs):with cls._instance_lock:if not hasattr(Singleton,'_instance'):Singleton._instance=object.__new__(cls)return Singleton._instancedef task():obj = Singleton()for i in range(10):t=threading.Thread(target=task)t.start()

3.利用类实现单例模式:

a.不能支持多线程的单例模式

class Singleton(object):@classmethoddef instance(cls,*args,**kwargs):if not  hasattr(Singleton,'_instance'):Singleton._instance=Singleton()return Singleton._instancea=Singleton.instance()
b=Singleton.instance()
print(a==b)#True

但是我们加上多线程试试

import time
class Singleton(object):def __init__(self):time.sleep(1)@classmethoddef instance(cls,*args,**kwargs):if not  hasattr(Singleton,'_instance'):Singleton._instance=Singleton()return Singleton._instance# a=Singleton.instance()
# b=Singleton.instance()
# print(a==b)
import threading
def task():obj = Singleton.instance()print(obj)for i in range(10):t=threading.Thread(target=task)t.start()

结果:

D:\virtualenv\envs\vuedjango\Scripts\python.exe D:/test/flaskTest/flaskpro3/单例模式/类.py
<__main__.Singleton object at 0x0000022E579C6E80>
<__main__.Singleton object at 0x0000022E579AB898>
<__main__.Singleton object at 0x0000022E579EC6A0>
<__main__.Singleton object at 0x0000022E579DB1D0>
<__main__.Singleton object at 0x0000022E579EC5C0>
<__main__.Singleton object at 0x0000022E579D1FD0>
<__main__.Singleton object at 0x0000022E579D9C50>
<__main__.Singleton object at 0x0000022E579C6F60>
<__main__.Singleton object at 0x0000022E579D1EB8>
<__main__.Singleton object at 0x0000022E579DB2B0>Process finished with exit code 0

b.解决上面存在的问题,实现支持多线程的单列模式:

import time
import threading
class Singleton(object):_instance_lock = threading.Lock()def __init__(self):time.sleep(1)@classmethoddef instance(cls,*args,**kwargs):with cls._instance_lock:if not hasattr(Singleton,'_instance'):Singleton._instance=Singleton()return Singleton._instancereturn Singleton._instancedef task():obj = Singleton.instance()print(obj)for i in range(10):t=threading.Thread(target=task)t.start()

结果:

D:\virtualenv\envs\vuedjango\Scripts\python.exe D:/test/flaskTest/flaskpro3/单例模式/类.py
<__main__.Singleton object at 0x000001BADB56F320>
<__main__.Singleton object at 0x000001BADB56F320>
<__main__.Singleton object at 0x000001BADB56F320>
<__main__.Singleton object at 0x000001BADB56F320>
<__main__.Singleton object at 0x000001BADB56F320>
<__main__.Singleton object at 0x000001BADB56F320>
<__main__.Singleton object at 0x000001BADB56F320>
<__main__.Singleton object at 0x000001BADB56F320>
<__main__.Singleton object at 0x000001BADB56F320>
<__main__.Singleton object at 0x000001BADB56F320>Process finished with exit code 0

问题:

创建实例只能调用Singleton.instance()来调用,不能用Singleton()来实现

四、基于metaclass方式实现

1.对象是类创建,创建对象时候类的init__方法自动执行,对象()执行类的 _ call_ 方法 2.类是type创建,创建类时候type的_init_方法自动执行,类() 执行type的 _call_方法(类的_new_方法,类的__init方法)

#Python学习交流QQ群:579817333
# 第0步: 执行type的 __init__ 方法【类是type的对象】
class Foo:def __init__(self):passdef __call__(self, *args, **kwargs):pass# 第1步: 执行type的 __call__ 方法
#        1.1  调用 Foo类(是type的对象)的 __new__方法,用于创建对象。
#        1.2  调用 Foo类(是type的对象)的 __init__方法,用于对对象初始化。
obj = Foo()
# 第2步:执行Foodef __call__ 方法
obj()

class SingletonType(type):def __init__(self,*args,**kwargs):print(1)super(SingletonType,self).__init__(*args,**kwargs)def __call__(cls, *args, **kwargs):print(2)obj = cls.__new__(cls,*args, **kwargs)cls.__init__(obj,*args, **kwargs) # Foo.__init__(obj)return objclass Foo(metaclass=SingletonType):def __init__(self,name):print(4)self.name = namedef __new__(cls, *args, **kwargs):print(3)return object.__new__(cls)obj1 = Foo('name')

实现单例

import threading
class Singleton(type):_instance_lock=threading.Lock()def __call__(cls, *args, **kwargs):with  cls._instance_lock:if not hasattr(cls,'_instance'):cls._instance=super(Singleton, cls).__call__(*args, **kwargs)return cls._instanceclass Foo(metaclass=Singleton):def __init__(self,name):self.name=nameobj1 = Foo('name')
obj2 = Foo('name')
print(obj1,obj2)

完)

Python单例模式4种方式相关推荐

  1. python最简单单例模式_5种Python单例模式的实现方式

    本文为大家分享了Python创建单例模式的5种常用方法,供大家参考,具体内容如下 所谓单例,是指一个类的实例从始至终只能被创建一次. 方法1: 如果想使得某个类从始至终最多只有一个实例,使用__new ...

  2. python单例模式代码-5种Python单例模式的实现方式

    本文为大家分享了Python创建单例模式的5种常用方法,供大家参考,具体内容如下 所谓单例,是指一个类的实例从始至终只能被创建一次. 方法1: 如果想使得某个类从始至终最多只有一个实例,使用__new ...

  3. python3解释器执行not 1 and 1_编程语言的分类,python解释器多版本共存.执行python的两种方式,变量,用户与程序交互...

    一.编程语言的分类? 机器语言:直接使用二进制指令编程,直接操作硬件,必须考虑硬件细节. 汇编语言:用简写的英文标识符取代二进制去编写程序,直接操作硬件,必须考虑硬件细节. 高级语言:通过人类能够理解 ...

  4. 运行python的两种方式磁盘式_python计算机基础-Day1

    计算机基础-Day1 一.计算机基础 首先Python是一门编程语言 语言: 那什么是语言?语言就是一种事物与另一种事物沟通的介质. 所以说编程语言是程序员跟计算机沟通的介质,那么为什么要跟计算机沟通 ...

  5. 详解python运行三种方式_详解python运行三种方式

    方式一 交互式编程 交互式编程不需要创建脚本文件,是通过 Python 解释器的交互模式进来编写代码. linux上你只需要在命令行中输入 Python 命令即可启动交互式编程,提示窗口如下: $ p ...

  6. Python入门——运行python的两种方式变量常量

    一.运行python的两种方式 1. 交互式环境:输入代码立即执行,得到结果 优点:调试程序方便 缺点:无法永久保存程序 2. 命令行:python3 D:\test.txt 优点:以文件的方式将代码 ...

  7. python 收发微信之一:利用 WxPusher 的 web api 及 python SDK 两种方式给自己发微信

    目 录 摘要 实操 代码分析 需求来源与路径选择 参考 摘要 本文给出利用 WxPusher 提供的 web api 与 python SDK 两种方式,实现微信发送的 python 代码样例,并简单 ...

  8. python的运行方式_详解python运行三种方式

    方式一 交互式编程 交互式编程不需要创建脚本文件,是通过 Python 解释器的交互模式进来编写代码. linux上你只需要在命令行中输入 Python 命令即可启动交互式编程,提示窗口如下: $ p ...

  9. 英伟达Jeston nano<3>使用Python实现三种方式串口通信

    英伟达Jeston nano<3>使用Python实现三种方式串口通信 前言 通信配置过程 基本信息 配置过程 方案一:Python-40pinEXpansion Header 方案二:P ...

  10. python手机版怎么运行项目或脚本-详解python运行三种方式

    方式一 交互式编程 交互式编程不需要创建脚本文件,是通过 Python 解释器的交互模式进来编写代码. linux上你只需要在命令行中输入 Python 命令即可启动交互式编程,提示窗口如下: $ p ...

最新文章

  1. Linux 之父归来!
  2. nacos 配置动态刷新_nacos配置中心修改后刷新
  3. 导入python库linux_Linux下Python安装PyMySQL成功,但无法导入的问题
  4. JVM,JDK,JRE和OpenJDK有什么区别?
  5. MySQL主从复制详细配置步骤及复制延时问题解决
  6. 小猫的java基础知识点汇总(下)
  7. python编程一球从100米_Python练习题 015:一颗自由落地的球
  8. python3生成器_Python3.7之生成器
  9. spring Bean的作用域(注解 单例 多例)
  10. 清空visual studio 开发缓存
  11. android 批量扫描,Android:连续扫描所有AP(接入点)
  12. 九江学院计算机考研,2017年江西财经大学与九江学院联合培养考研招生事宜的通知...
  13. Android Assets里的资源保存本地
  14. 重大建设项目土地勘测定界涉及基本农田怎么计算
  15. -XX:PretenureSizeThreshold的默认值和作用浅析
  16. linux系统的drm配置mipi,Linux 进阶 DRM等.....
  17. QScrollArea样式设置
  18. 如何显示隐藏的 Chrome 扩展程序图标
  19. zabbix微信报警
  20. 深入理解Amazon Alexa Skill(三)

热门文章

  1. 安装了天正电气 服务器为空,解决 WIN7_64位系统安装 天正电气2014+CAD2008时,出现“error”或者:“不能访问到网络锁……”...
  2. Language Models are unsupervised multitask learners
  3. gbdt python_GBDT回归的原理及Python实现
  4. 世界第一黑客:凯文.米特尼克
  5. python程序设计基础课后答案-python语言程序设计基础(第2版)课后答案嵩天
  6. 自然语言处理NLP开源软件工具包
  7. 代码该怎么写——设计原则
  8. java cobar_Cobar源码解析(二)
  9. jwplayer使用方法
  10. 教你如何下载抖音视频的背景音乐?是音乐不是视频哦