常见的在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实现apahce网站日志分析示例
Apr 02 Python
Python3基础之输入和输出实例分析
Aug 18 Python
Django URL传递参数的方法总结
Aug 28 Python
pandas重新生成索引的方法
Nov 06 Python
python中的句柄操作的方法示例
Jun 20 Python
python写日志文件操作类与应用示例
Jul 01 Python
python模拟鼠标点击和键盘输入的操作
Aug 04 Python
python3 配置logging日志类的操作
Apr 08 Python
python 画图 图例自由定义方式
Apr 17 Python
python sitk.show()与imageJ结合使用常见的问题
Apr 20 Python
python dict乱码如何解决
Jun 07 Python
tensorflow+k-means聚类简单实现猫狗图像分类的方法
Apr 28 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
php使用Smarty的相关注意事项及访问变量的几种方式
2011/12/08 PHP
PHP求小于1000的所有水仙花数的代码
2012/01/10 PHP
php控制linux服务器常用功能 关机 重启 开新站点等
2012/09/05 PHP
CI框架实现框架前后端分离的方法详解
2016/12/30 PHP
Laravel 5使用Laravel Excel实现Excel/CSV文件导入导出的功能详解
2017/10/11 PHP
用cssText批量修改样式
2009/08/29 Javascript
javascript GUID生成器实现代码
2009/10/31 Javascript
跟着JQuery API学Jquery 之三 筛选
2010/04/09 Javascript
jQuery DOM操作实例
2014/03/05 Javascript
推荐一款jQuery插件模板
2015/01/09 Javascript
jQuery实现在textarea指定位置插入字符或表情的方法
2015/03/11 Javascript
JavaScript控制网页层收起和展开效果的方法
2015/04/15 Javascript
可以浮动某个物体的jquery控件用法实例
2015/07/24 Javascript
Bootstrap登陆注册页面开发教程
2016/07/12 Javascript
引用jquery框架后出错的解决方法
2016/08/09 Javascript
JavaScript cookie详解及简单实例应用
2016/12/31 Javascript
尝试自己动手用react来写一个分页组件(小结)
2018/02/09 Javascript
Vue-cropper 图片裁剪的基本原理及思路讲解
2018/04/17 Javascript
Vue-CLI3.x 设置反向代理的方法
2018/12/06 Javascript
vue实现购物车抛物线小球动画效果的方法详解
2019/02/13 Javascript
ES6 async、await的基本使用方法示例
2020/06/06 Javascript
[38:21]2018DOTA2亚洲邀请赛3月30日 小组赛A组 LGD VS Newbee
2018/03/31 DOTA
Python THREADING模块中的JOIN()方法深入理解
2015/02/18 Python
python绘制热力图heatmap
2020/03/23 Python
OpenCV+face++实现实时人脸识别解锁功能
2019/08/28 Python
利用python如何实现猫捉老鼠小游戏
2020/12/04 Python
基于canvas的骨骼动画的示例代码
2018/06/12 HTML / CSS
Brora官网:英国领先的羊绒服装品牌
2019/08/28 全球购物
期末自我鉴定
2014/01/23 职场文书
新浪微博实习心得体会
2014/01/27 职场文书
老总助理工作岗位职责
2014/02/06 职场文书
《少年王冕》教学反思
2014/04/11 职场文书
质量负责人任命书
2014/06/06 职场文书
物流专业专科生职业生涯规划书
2014/09/14 职场文书
担保书范本
2015/01/20 职场文书
校长一岗双责责任书
2015/05/09 职场文书