常见的在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实现ssh批量登录并执行命令
Oct 25 Python
python实现数据预处理之填充缺失值的示例
Dec 22 Python
python中将字典形式的数据循环插入Excel
Jan 16 Python
[原创]windows下Anaconda的安装与配置正解(Anaconda入门教程)
Apr 05 Python
pandas 将list切分后存入DataFrame中的实例
Jul 03 Python
python实现屏保程序(适用于背单词)
Jul 30 Python
Python input函数使用实例解析
Nov 22 Python
Python 过滤错误log并导出的实例
Dec 26 Python
python使用pyecharts库画地图数据可视化的实现
Mar 25 Python
基于Python的接口自动化unittest测试框架和ddt数据驱动详解
Jan 27 Python
利用python实时刷新基金估值(摸鱼小工具)
Sep 15 Python
Python实现制作销售数据可视化看板详解
Nov 27 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中配置文件现在需要绝密的短语密码的解决方法
2007/02/11 PHP
php UBB 解析实现代码
2011/11/27 PHP
JS BASE64编码 window.atob(), window.btoa()
2021/03/09 Javascript
js querySelector和getElementById通过id获取元素的区别
2012/04/20 Javascript
JS截取字符串常用方法整理及使用示例
2013/10/18 Javascript
图片翻转效果具体实现代码
2014/01/09 Javascript
Window.Open如何在同一个标签页打开
2014/06/20 Javascript
在JS数组特定索引处指定位置插入元素的技巧
2014/08/24 Javascript
一个JavaScript函数把URL参数解析成Json对象
2014/09/24 Javascript
基于jquery实现页面滚动到底自动加载数据的功能
2015/12/19 Javascript
使用jQuery给input标签设置默认值
2016/06/20 Javascript
前端微信支付js代码
2016/07/25 Javascript
JavaScript制作简单分页插件
2016/09/11 Javascript
win系统下nodejs环境安装配置
2017/05/04 NodeJs
vue mint-ui学习笔记之picker的使用
2017/10/11 Javascript
微信小程序实现页面分享onShareAppMessage
2019/08/12 Javascript
Python学习pygal绘制线图代码分享
2017/12/09 Python
解决python线程卡死的问题
2019/02/18 Python
Python实现合并excel表格的方法分析
2019/04/13 Python
Pandas之Fillna填充缺失数据的方法
2019/06/25 Python
python将excel转换为csv的代码方法总结
2019/07/03 Python
Python实现加密的RAR文件解压的方法(密码已知)
2020/09/11 Python
全球性的众包图形设计市场:DesignCrowd
2021/02/02 全球购物
工程概预算专业毕业生求职信
2013/10/04 职场文书
护士个人简历自荐信
2013/10/18 职场文书
大学生个人事迹材料
2014/01/21 职场文书
党校学习自我鉴定
2014/02/24 职场文书
商务英语专业毕业生求职信
2014/07/06 职场文书
学生检讨书如何写
2014/10/30 职场文书
2015年度党员个人总结
2015/02/14 职场文书
目标责任书格式范文
2015/05/11 职场文书
2015年学校信息技术工作总结
2015/05/25 职场文书
宣传稿格式范文
2015/07/23 职场文书
建国70周年的心得体会(2篇)
2019/09/20 职场文书
抖音动画片,皮皮虾,《治愈系》动画在用这首REMIX作为背景音乐,Anak ,The last world with you完整版
2022/03/16 杂记
vue中this.$http.post()跨域和请求参数丢失的解决
2022/04/08 Vue.js