常见的在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模拟登陆淘宝并统计淘宝消费情况的代码实例分享
Jul 04 Python
Python自定义函数实现求两个数最大公约数、最小公倍数示例
May 21 Python
Python实现的简单排列组合算法示例
Jul 04 Python
Flask核心机制之上下文源码剖析
Dec 25 Python
Django unittest 设置跳过某些case的方法
Dec 26 Python
Python利用heapq实现一个优先级队列的方法
Feb 03 Python
Python把对应格式的csv文件转换成字典类型存储脚本的方法
Feb 12 Python
python实现在函数图像上添加文字和标注的方法
Jul 08 Python
使用python画社交网络图实例代码
Jul 10 Python
python使用opencv在Windows下调用摄像头实现解析
Nov 26 Python
Anaconda的安装及其环境变量的配置详解
Apr 22 Python
python中出现invalid syntax报错的几种原因分析
Feb 12 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
phpMyAdmin链接MySql错误 个人解决方案
2009/12/28 PHP
PHP访问数据库集群的方法小结
2016/03/14 PHP
php实现获取近几日、月时间示例
2019/07/06 PHP
php测试kafka项目示例
2020/02/06 PHP
php中array_fill函数的实例用法
2021/03/02 PHP
JQuery团队打造的javascript单元测试工具QUnit介绍
2010/02/26 Javascript
基于IE下ul li 互相嵌套时的bug,排查,解决过程以及心得介绍
2013/05/07 Javascript
JavaScript 垃圾回收机制分析
2013/10/10 Javascript
JS实现仿百度输入框自动匹配功能的示例代码
2014/02/19 Javascript
js网页右下角提示框实例
2014/10/14 Javascript
JavaScript获取网页表单提交方式的方法
2015/04/02 Javascript
JavaScript函数使用的基本教程
2015/06/04 Javascript
js实现浏览器倒计时跳转页面效果
2016/08/12 Javascript
利用Javascript裁剪图片并存储的简单实现
2017/03/13 Javascript
Vue项目中quill-editor带样式编辑器的使用方法
2017/08/08 Javascript
webpack的pitching loader详解
2019/09/23 Javascript
浅谈Layui的eleTree树式选择器使用方法
2019/09/25 Javascript
JS如何实现手机端输入验证码效果
2020/05/13 Javascript
jQuery实现异步上传一个或多个文件
2020/08/17 jQuery
在Vue中使用Echarts可视化库的完整步骤记录
2020/11/18 Vue.js
[01:28:31]《加油DOTA》真人秀 第五期
2014/09/01 DOTA
[54:30]Liquid vs Newbee 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
Python解析网页源代码中的115网盘链接实例
2014/09/30 Python
python使用smtplib模块通过gmail实现邮件发送的方法
2015/05/08 Python
python实时分析日志的一个小脚本分享
2017/05/07 Python
将python包发布到PyPI和制作whl文件方式
2019/12/25 Python
Python3操作YAML文件格式方法解析
2020/04/10 Python
如何用Python徒手写线性回归
2021/01/25 Python
python 实现IP子网计算
2021/02/18 Python
CSS3 实现倒计时效果
2020/11/25 HTML / CSS
C语言怎样定义和声明全局变量和函数最好
2013/11/26 面试题
记账会计岗位职责
2014/06/16 职场文书
要账委托书范本
2014/09/15 职场文书
领导班子在批评与自我批评座谈会上的发言
2014/09/28 职场文书
教师作风整改措施思想汇报
2014/10/12 职场文书