常见的在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基础入门详解(文件输入/输出 内建类型 字典操作使用方法)
Dec 08 Python
python实现多线程的两种方式
May 22 Python
Python实现Linux中的du命令
Jun 12 Python
python编程线性回归代码示例
Dec 07 Python
Python实现找出数组中第2大数字的方法示例
Mar 26 Python
pyqt5的QComboBox 使用模板的具体方法
Sep 06 Python
python set内置函数的具体使用
Jul 02 Python
python中的TCP(传输控制协议)用法实例分析
Nov 15 Python
Keras搭建自编码器操作
Jul 03 Python
Pycharm的Available Packages为空的解决方法
Sep 18 Python
Python绘制词云图之可视化神器pyecharts的方法
Feb 23 Python
详解python第三方库的安装、PyInstaller库、random库
Mar 03 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
Thinkphp的volist标签嵌套循环使用教程
2014/07/08 PHP
php绘制一条直线的方法
2015/01/24 PHP
Twig模板引擎用法入门教程
2016/01/20 PHP
php版微信公众平台之微信网页登陆授权示例
2016/09/23 PHP
PHP中的函数声明与使用详解
2017/05/27 PHP
Docker搭建自己的PHP开发环境
2018/02/24 PHP
JavaScript静态的动态
2006/09/18 Javascript
JavaScript 基于原型的对象(创建、调用)
2009/10/16 Javascript
ASP 过滤数组重复数据函数(加强版)
2010/05/31 Javascript
js控制页面控件隐藏显示的两种方法介绍
2013/10/09 Javascript
简单js代码实现selece二级联动(推荐)
2014/02/18 Javascript
7个JS基础知识总结
2014/03/05 Javascript
JavaScript DOM基础
2015/04/13 Javascript
jquery带下拉菜单和焦点图代码分享
2015/08/24 Javascript
jQuery如何使用自动触发事件trigger
2015/11/29 Javascript
Bootstrap+jfinal退出系统弹出确认框的实现方法
2016/05/30 Javascript
JavaScript实现仿Clock ISO时钟
2018/06/29 Javascript
JS canvas绘制五子棋的棋盘
2020/05/28 Javascript
小程序实现订单倒计时功能
2019/04/23 Javascript
vue登录页面cookie的使用及页面跳转代码
2019/07/10 Javascript
15个简单的JS编码标准让你的代码更整洁(小结)
2020/07/16 Javascript
Python中super()函数简介及用法分享
2016/07/11 Python
python使用json序列化datetime类型实例解析
2018/02/11 Python
Python实现Linux监控的方法
2019/05/16 Python
在python plt图表中文字大小调节的方法
2019/07/08 Python
Django之使用内置函数和celery发邮件的方法示例
2019/09/16 Python
pygame实现俄罗斯方块游戏(基础篇3)
2019/10/29 Python
Selenium 滚动页面至元素可见的方法
2020/03/18 Python
使用CSS3编写类似iOS中的复选框及带开关的按钮
2016/04/11 HTML / CSS
Carolina工作鞋官网:Carolina Footwear
2019/03/14 全球购物
英国医生在线预约:Top Doctors
2019/10/30 全球购物
Lentiamo丹麦:购买便宜的隐形眼镜
2021/01/13 全球购物
职专应届生求职信
2013/11/16 职场文书
秋季婚礼证婚词
2014/01/11 职场文书
群众路线学习心得体会范文
2014/11/05 职场文书
泰坦尼克号观后感
2015/06/04 职场文书