单利模式及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通过ftplib登录到ftp服务器的方法
May 08 Python
Python中利用Scipy包的SIFT方法进行图片识别的实例教程
Jun 03 Python
python虚拟环境virtualenv的使用教程
Oct 20 Python
Python使用wget实现下载网络文件功能示例
May 31 Python
启动Atom并运行python文件的步骤
Nov 09 Python
利用Django提供的ModelForm增删改数据的方法
Jan 06 Python
在Pycharm中修改文件默认打开方式的方法
Jan 17 Python
python3实现逐字输出的方法
Jan 23 Python
在django-xadmin中APScheduler的启动初始化实例
Nov 15 Python
python爬虫开发之使用python爬虫库requests,urllib与今日头条搜索功能爬取搜索内容实例
Mar 10 Python
完美解决Django2.0中models下的ForeignKey()问题
May 19 Python
Pytorch如何切换 cpu和gpu的使用详解
Mar 01 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
短波的认识
2021/03/01 无线电
php 上传功能实例代码
2010/04/13 PHP
php下mysql数据库操作类(改自discuz)
2010/07/03 PHP
php excel类 phpExcel使用方法介绍
2010/08/21 PHP
php学习之运算符相关概念
2011/06/09 PHP
php安全之直接用$获取值而不$_GET 字符转义
2012/06/03 PHP
纯PHP生成的一个树叶图片画图例子
2014/04/16 PHP
详解PHP的Yii框架中自带的前端资源包的使用
2016/03/31 PHP
php similar_text()函数的定义和用法
2016/05/12 PHP
php array_udiff_assoc 计算两个数组的差集实例
2016/11/12 PHP
thinkphp框架使用JWTtoken的方法详解
2019/10/10 PHP
js/jquery解析json和数组格式的方法详解
2014/01/09 Javascript
JavaScript中逗号运算符介绍及使用示例
2015/03/13 Javascript
JS/Jquery判断对象为空的方法
2015/06/11 Javascript
初识简单却不失优雅的Vue.js
2016/09/12 Javascript
打造自己的jQuery插件入门教程
2016/09/23 Javascript
jquery的父、子、兄弟节点查找,节点的子节点循环方法
2016/12/07 Javascript
Mint UI 基于 Vue.js 移动端组件库
2017/11/07 Javascript
element-ui带输入建议的input框踩坑(输入建议空白以及会闪出上一次的输入建议问题)
2019/01/15 Javascript
[01:51]开启你的城市传奇 完美世界城市挑战赛开始报名
2018/10/09 DOTA
python 获取et和excel的版本号
2009/04/09 Python
使用Python将数组的元素导出到变量中(unpacking)
2016/10/27 Python
Python爬虫之正则表达式的使用教程详解
2018/10/25 Python
pycharm debug功能实现跳到循环末尾的方法
2018/11/29 Python
Django自带日志 settings.py文件配置方法
2019/08/30 Python
python Popen 获取输出,等待运行完成示例
2019/12/30 Python
在win64上使用bypy进行百度网盘文件上传功能
2020/01/02 Python
洛佩桑酒店官方网站:Lopesan Hotels
2019/04/15 全球购物
sort命令的作用和用法
2012/11/04 面试题
【魔兽争霸3重制版】原版画面与淬火MOD画面对比
2021/03/26 魔兽争霸
物业保安员岗位职责
2014/03/14 职场文书
教师节宣传方案
2014/05/23 职场文书
2014年科室工作总结范文
2014/12/19 职场文书
浅谈mysql返回Boolean类型的几种情况
2021/06/04 MySQL
MySQL 四种连接和多表查询详解
2021/07/16 MySQL
Java org.w3c.dom.Document 类方法引用报错
2021/08/07 Java/Android