单利模式及python实现方式详解


Posted in Python onMarch 20, 2018

单例模式

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

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

python实现单例模式

使用模块实现

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

mysingleton.py

class Singleton:
  def foo(self):
    print('foo')
singleton=Singleton()

其他文件

from mysingleton import singleton
singleton.foo()

装饰器实现

def singleton(cls):
  _instance = {}
  def wraper(*args, **kargs):
    if cls not in _instance:
      _instance[cls] = cls(*args, **kargs)
    return _instance[cls]
  return wraper
@singleton
class A(object):
  def __init__(self, x=0):
    self.x = x
a1 = A(2)
a2 = A(3)

最终实例化出一个对象并且保存在_instance中,_instance的值也一定是

基于__new__方法实现

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

class Singleton():
  def __new__(cls, *args, **kwargs):
    if not hasattr(cls,'_instance'):
      cls._instance=object.__new__(cls)
    return cls._instance

class A(Singleton):
  def __init__(self,x):
    self.x=x

a=A('han')
b=A('tao')
print(a.x)
print(b.x)

为了保证线程安全需要在内部加入锁

import threading

class Singleton():
  lock=threading.Lock
  def __new__(cls, *args, **kwargs):
    if not hasattr(cls,'_instance'):
      with cls.lock:
        if not hasattr(cls, '_instance'):
          cls._instance=object.__new__(cls)
    return cls._instance
class A(Singleton):
  def __init__(self,x):
    self.x=x
a=A('han')
b=A('tao')
print(a.x)
print(b.x)

两大注意:

1. 除了模块单例外,其他几种模式的本质都是通过设置中间变量,来判断类是否已经被实例。中间变量的访问和更改存在线程安全的问题:在开启多线程模式的时候需要加锁处理。

2.  __new__方法无法避免触发__init__(),初始的成员变量会进行覆盖。 其他方法不会。

PS:下面看下Python单例模式的4种实现方法

#-*- encoding=utf-8 -*- 
print '----------------------方法1--------------------------' 
#方法1,实现__new__方法 
#并在将一个类的实例绑定到类变量_instance上, 
#如果cls._instance为None说明该类还没有实例化过,实例化该类,并返回 
#如果cls._instance不为None,直接返回cls._instance 
class Singleton(object): 
  def __new__(cls, *args, **kw): 
    if not hasattr(cls, '_instance'): 
      orig = super(Singleton, cls) 
      cls._instance = orig.__new__(cls, *args, **kw) 
    return cls._instance 
class MyClass(Singleton): 
  a = 1 
one = MyClass() 
two = MyClass() 
two.a = 3 
print one.a 
#3 
#one和two完全相同,可以用id(), ==, is检测 
print id(one) 
#29097904 
print id(two) 
#29097904 
print one == two 
#True 
print one is two 
#True 
print '----------------------方法2--------------------------' 
#方法2,共享属性;所谓单例就是所有引用(实例、对象)拥有相同的状态(属性)和行为(方法) 
#同一个类的所有实例天然拥有相同的行为(方法), 
#只需要保证同一个类的所有实例具有相同的状态(属性)即可 
#所有实例共享属性的最简单最直接的方法就是__dict__属性指向(引用)同一个字典(dict) 
#可参看:http://code.activestate.com/recipes/66531/ 
class Borg(object): 
  _state = {} 
  def __new__(cls, *args, **kw): 
    ob = super(Borg, cls).__new__(cls, *args, **kw) 
    ob.__dict__ = cls._state 
    return ob 
class MyClass2(Borg): 
  a = 1 
one = MyClass2() 
two = MyClass2() 
#one和two是两个不同的对象,id, ==, is对比结果可看出 
two.a = 3 
print one.a 
#3 
print id(one) 
#28873680 
print id(two) 
#28873712 
print one == two 
#False 
print one is two 
#False 
#但是one和two具有相同的(同一个__dict__属性),见: 
print id(one.__dict__) 
#30104000 
print id(two.__dict__) 
#30104000 
print '----------------------方法3--------------------------' 
#方法3:本质上是方法1的升级(或者说高级)版 
#使用__metaclass__(元类)的高级python用法 
class Singleton2(type): 
  def __init__(cls, name, bases, dict): 
    super(Singleton2, cls).__init__(name, bases, dict) 
    cls._instance = None 
  def __call__(cls, *args, **kw): 
    if cls._instance is None: 
      cls._instance = super(Singleton2, cls).__call__(*args, **kw) 
    return cls._instance 
class MyClass3(object): 
  __metaclass__ = Singleton2 
one = MyClass3() 
two = MyClass3() 
two.a = 3 
print one.a 
#3 
print id(one) 
#31495472 
print id(two) 
#31495472 
print one == two 
#True 
print one is two 
#True 
print '----------------------方法4--------------------------' 
#方法4:也是方法1的升级(高级)版本, 
#使用装饰器(decorator), 
#这是一种更pythonic,更elegant的方法, 
#单例类本身根本不知道自己是单例的,因为他本身(自己的代码)并不是单例的 
def singleton(cls, *args, **kw): 
  instances = {} 
  def _singleton(): 
    if cls not in instances: 
      instances[cls] = cls(*args, **kw) 
    return instances[cls] 
  return _singleton 
@singleton 
class MyClass4(object): 
  a = 1 
  def __init__(self, x=0): 
    self.x = x 
one = MyClass4() 
two = MyClass4() 
two.a = 3 
print one.a 
#3 
print id(one) 
#29660784 
print id(two) 
#29660784 
print one == two 
#True 
print one is two 
#True 
one.x = 1 
print one.x 
#1 
print two.x 
#1

总结

以上所述是小编给大家介绍的python实现单利模式方式方式详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Python 相关文章推荐
Python程序设计入门(5)类的使用简介
Jun 16 Python
Python xlwt设置excel单元格字体及格式
Apr 18 Python
Python实现识别手写数字大纲
Jan 29 Python
python 删除指定时间间隔之前的文件实例
Apr 24 Python
django admin 后台实现三级联动的示例代码
Jun 22 Python
python3+pyqt5+itchat微信定时发送消息的方法
Feb 20 Python
Python Datetime模块和Calendar模块用法实例分析
Apr 15 Python
python识别图像并提取文字的实现方法
Jun 28 Python
Python 实现数组相减示例
Dec 27 Python
使用tensorflow实现矩阵分解方式
Feb 07 Python
基于Python的OCR实现示例
Apr 03 Python
python 监控服务器是否有人远程登录(详细思路+代码)
Dec 18 Python
python如何去除字符串中不想要的字符
Jul 05 #Python
python删除某个字符
Mar 19 #Python
Python 字符串操作(string替换、删除、截取、复制、连接、比较、查找、包含、大小写转换、分割等)
Mar 19 #Python
Python3 replace()函数使用方法
Mar 19 #Python
python将文本中的空格替换为换行的方法
Mar 19 #Python
python去掉空白行的多种实现代码
Mar 19 #Python
python奇偶行分开存储实现代码
Mar 19 #Python
You might like
sony ICF-2010 拆解与改装
2021/03/02 无线电
PHP HTML JavaScript MySQL代码如何互相传值的方法分享
2012/09/30 PHP
解析php二分法查找数组是否包含某一元素
2013/05/23 PHP
php实现在线生成条形码示例分享(条形码生成器)
2013/12/30 PHP
Thinkphp调用Image类生成缩略图的方法
2015/03/07 PHP
PHP设计模式之工厂模式(Factory Pattern)的讲解
2019/03/21 PHP
PHP常量及变量区别原理详解
2020/08/14 PHP
javascript 表单验证常见正则
2009/09/28 Javascript
js+数组实现网页上显示时间/星期几的实用方法
2013/01/18 Javascript
利用js实现遮罩以及弹出可移动登录窗口
2013/07/08 Javascript
加随机数引入脚本不让浏览器读取缓存
2014/09/04 Javascript
javascript原型继承工作原理和实例详解
2016/04/07 Javascript
Backbone.js框架中Model与Collection的使用实例
2016/05/07 Javascript
vue.js的提示组件
2017/03/02 Javascript
jQuery插件echarts实现的多折线图效果示例【附demo源码下载】
2017/03/04 Javascript
基于JS对象创建常用方式及原理分析
2017/06/28 Javascript
JS中关于正则的巧妙操作
2017/08/31 Javascript
JS中Object对象的原型概念基础
2018/01/29 Javascript
弱类型语言javascript中 a,b 的运算实例小结
2019/08/07 Javascript
vue源码nextTick使用及原理解析
2019/08/13 Javascript
Vue打包后访问静态资源路径问题
2019/11/08 Javascript
JS数据类型判断的几种常用方法
2020/07/07 Javascript
python绘制中国大陆人口热力图
2018/11/07 Python
Python3爬楼梯算法示例
2019/03/04 Python
python3.4 将16进制转成字符串的实例
2019/06/12 Python
详解将Python程序(.py)转换为Windows可执行文件(.exe)
2019/07/19 Python
如何将PySpark导入Python的放实现(2种)
2020/04/26 Python
10 套华丽的CSS3 按钮小结
2012/10/03 HTML / CSS
泰国折扣酒店预订:Hotels2Thailand
2018/03/20 全球购物
英国最大的笔记本电脑直销专家:Laptops Direct
2019/07/20 全球购物
如何启动时不需输入用户名与密码
2014/05/09 面试题
毕业学生推荐信
2013/12/01 职场文书
个人优缺点自我评价
2014/01/27 职场文书
个人买房协议书范本
2014/10/06 职场文书
如何利用Matlab制作一款真正的拼图小游戏
2021/05/11 Python
Arthas排查Kubernetes中应用频繁挂掉重启异常
2022/02/28 MySQL