常见的在Python中实现单例模式的三种方法


Posted in Python onApril 08, 2015

单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。

单例模式的要点有三个;一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。在Python中,单例模式有以下几种实现方式。

方法一、实现__new__方法,然后将类的一个实例绑定到类变量_instance上;如果cls._instance为None,则说明该类还没有被实例化过,new一个该类的实例,并返回;如果cls._instance不为None,直接返回_instance,代码如下:

class Singleton(object):
 
  def __new__(cls, *args, **kwargs):
    if not hasattr(cls, '_instance'):
      orig = super(Singleton, cls)
      cls._instance = orig.__new__(cls, *args, **kwargs)
    return cls._instance
 
class MyClass(Singleton):
  a = 1
 
one = MyClass()
two = MyClass()
 
#one和two完全相同,可以用id(), ==, is检测
print id(one)  # 29097904
print id(two)  # 29097904
print one == two  # True
print one is two  # True

方法二、本质上是方法一的升级版,使用__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, **kwargs):
    if cls._instance is None:
      cls._instance = super(Singleton2, cls).__call__(*args, **kwargs)
    return cls._instance
 
class MyClass2(object):
  __metaclass__ = Singleton2
  a = 1
 
one = MyClass2()
two = MyClass2()
 
print id(one)  # 31495472
print id(two)  # 31495472
print one == two  # True
print one is two  # True

方法三、使用Python的装饰器(decorator)实现单例模式,这是一种更Pythonic的方法;单利类本身的代码不是单例的,通装饰器使其单例化,代码如下:

def singleton(cls, *args, **kwargs):
  instances = {}
  def _singleton():
    if cls not in instances:
      instances[cls] = cls(*args, **kwargs)
    return instances[cls]
  return _singleton
 
@singleton
class MyClass3(object):
  a = 1
 
one = MyClass3()
two = MyClass3()
 
print id(one)  # 29660784
print id(two)  # 29660784
print one == two  # True
print one is two  # True
Python 相关文章推荐
python基础教程之实现石头剪刀布游戏示例
Feb 11 Python
Python中字典的基本知识初步介绍
May 21 Python
Python使用multiprocessing实现一个最简单的分布式作业调度系统
Mar 14 Python
python 求一个列表中所有元素的乘积实例
Jun 11 Python
解决python中用matplotlib画多幅图时出现图形部分重叠的问题
Jul 07 Python
python选取特定列 pandas iloc,loc,icol的使用详解(列切片及行切片)
Aug 06 Python
Python中求对数方法总结
Mar 10 Python
对Matlab中共轭、转置和共轭装置的区别说明
May 11 Python
pyecharts在数据可视化中的应用详解
Jun 08 Python
用于ETL的Python数据转换工具详解
Jul 21 Python
Linux安装Python3如何和系统自带的Python2并存
Jul 23 Python
Python爬虫基础初探selenium
May 31 Python
分析Python的Django框架的运行方式及处理流程
Apr 08 #Python
给Python的Django框架下搭建的BLOG添加RSS功能的教程
Apr 08 #Python
在Python中使用NLTK库实现对词干的提取的教程
Apr 08 #Python
使用Python操作Elasticsearch数据索引的教程
Apr 08 #Python
用Python实现协同过滤的教程
Apr 08 #Python
在Python中调用ggplot的三种方法
Apr 08 #Python
Python字符串和文件操作常用函数分析
Apr 08 #Python
You might like
第一个无线电台是由谁发明的
2021/03/01 无线电
ajax缓存问题解决途径
2006/12/06 PHP
分享十款最出色的PHP安全开发库中文详细介绍
2015/03/22 PHP
PHP实现生成推广海报的方法详解
2018/03/14 PHP
PHP实现的CURL非阻塞调用类
2018/07/26 PHP
Yii实现微信公众号场景二维码的方法实例
2020/08/30 PHP
js 函数调用模式小结
2011/12/26 Javascript
框架页面高度自动刷新的Javascript脚本
2013/11/01 Javascript
常见表单重复提交问题整理及解决方法
2013/11/13 Javascript
jquery对ajax的支持介绍
2013/12/10 Javascript
JQuery中使用.each()遍历元素学习笔记
2014/11/08 Javascript
jQuery表单美化插件jqTransform使用详解
2015/04/12 Javascript
js实现两点之间画线的方法
2015/05/12 Javascript
通过Jquery.cookie.js实现展示浏览网页的历史记录超管用
2015/10/23 Javascript
jQuery模拟360浏览器切屏效果幻灯片(附demo源码下载)
2016/01/29 Javascript
关于JavaScript 原型链的一点个人理解
2016/07/31 Javascript
浅谈JS中的!=、== 、!==、===的用法和区别
2016/09/24 Javascript
详解AngularJS ui-sref的简单使用
2017/04/24 Javascript
React Native如何消除启动时白屏的方法
2017/08/08 Javascript
input file样式修改以及图片预览删除功能详细概括(推荐)
2017/08/17 Javascript
vue中的inject学习教程
2019/04/24 Javascript
BootStrap表单验证中的非Submit类型按钮点击时触发验证的坑
2019/09/05 Javascript
如何区分vue中的v-show 与 v-if
2020/09/08 Javascript
[40:03]Liquid vs Optic 2018国际邀请赛淘汰赛BO3 第一场 8.21
2018/08/22 DOTA
[02:12]打造更好的电竞完美世界:完美盛典回顾篇
2018/12/19 DOTA
python将字符串以utf-8格式保存在txt文件中的方法
2018/10/30 Python
Python XML转Json之XML2Dict的使用方法
2019/01/15 Python
python 一篇文章搞懂装饰器所有用法(建议收藏)
2019/08/23 Python
使用Python实现画一个中国地图
2019/11/23 Python
意大利奢侈品购物网站:Giglio
2018/01/05 全球购物
岗位聘任书范文
2014/03/29 职场文书
学校党委干部个人对照检查材料思想汇报
2014/10/09 职场文书
学历证明样本
2015/06/16 职场文书
初级职称评定工作总结
2015/08/13 职场文书
保险公司岗前培训工作总结
2015/10/24 职场文书
画错魏国疆域啦!《派对咖孔明》动画因作画失误于官网致歉
2022/04/07 日漫