常见的在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使用PDFMiner解析PDF代码实例
Mar 27 Python
Python入门_浅谈字符串的分片与索引、字符串的方法
May 16 Python
python中 chr unichr ord函数的实例详解
Aug 06 Python
Python3 循环语句(for、while、break、range等)
Nov 20 Python
python3转换code128条形码的方法
Apr 17 Python
Django框架自定义模型管理器与元选项用法分析
Jul 22 Python
PyQt5基本控件使用之消息弹出、用户输入、文件对话框的使用方法
Aug 06 Python
python正则过滤字母、中文、数字及特殊字符方法详解
Feb 11 Python
python中元组的用法整理
Jun 15 Python
python爬虫---requests库的用法详解
Sep 28 Python
python从Oracle读取数据生成图表
Oct 14 Python
python 发送get请求接口详解
Nov 17 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的QRcode类与大家分享
2011/11/13 PHP
深入理解php的MySQL连接类
2013/06/07 PHP
如何在旧的PHP系统中使用PHP 5.3之后的库
2015/12/02 PHP
PHP读取mssql json数据中文乱码的解决办法
2016/04/11 PHP
PHP中Restful api 错误提示返回值实现思路
2016/04/12 PHP
jquery last-child 列表最后一项的样式
2010/01/22 Javascript
关于Mozilla浏览器不支持innerText的解决办法
2011/01/01 Javascript
使用正则表达式的格式化与高亮显示json字符串
2014/12/03 Javascript
jQuery实现360°全景拖动展示
2015/03/18 Javascript
7个去伪存真的JavaScript面试题
2016/01/07 Javascript
Bootstrap 粘页脚效果
2016/03/28 Javascript
JQuery实现动态操作表格
2017/01/11 Javascript
jquery easyui DataGrid简单示例
2017/01/23 Javascript
JS实现手写parseInt的方法示例
2017/09/24 Javascript
使用D3.js+Vue实现一个简单的柱形图
2018/08/05 Javascript
vue watch普通监听和深度监听实例详解(数组和对象)
2018/08/16 Javascript
Vue.js轮播图走马灯代码实例(全)
2019/05/08 Javascript
使用微信SDK自定义分享的方法
2019/07/03 Javascript
[41:12]Liquid vs Secret 2019国际邀请赛淘汰赛 败者组 BO3 第一场 8.24
2019/09/10 DOTA
使用Python3制作TCP端口扫描器
2017/04/17 Python
Diango + uwsgi + nginx项目部署的全过程(可外网访问)
2018/04/22 Python
python递归下载文件夹下所有文件
2019/08/31 Python
Python检测端口IP字符串是否合法
2020/06/05 Python
Python pip使用超时问题解决方案
2020/08/03 Python
魔幻般冒泡背景的CSS3按钮动画
2016/02/27 HTML / CSS
微软日本官方网站:Microsoft日本
2017/11/26 全球购物
英国鲜花递送:Blossoming Gifts
2020/07/10 全球购物
库房主管岗位职责
2013/12/31 职场文书
自立自强的名人事例
2014/02/10 职场文书
工作睡觉检讨书
2014/02/25 职场文书
院领导写的就业推荐信
2014/03/09 职场文书
2015年小学二年级班主任工作总结
2015/05/21 职场文书
仙境之桥观后感
2015/06/16 职场文书
酒桌上的祝酒词
2015/08/12 职场文书
一篇文章弄清楚Ajax请求的五个步骤
2022/03/17 Javascript
Elasticsearch Recovery 详细介绍
2022/04/19 Java/Android