博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
聊一聊python的单例模式
阅读量:6863 次
发布时间:2019-06-26

本文共 3009 字,大约阅读时间需要 10 分钟。

 

单例模式

 

单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。

四种方法:

  • 使用模块
  • 使用 __new__
  • 使用装饰器(decorator)
  • 使用元类(metaclass)
  • 使用类方法

 

1. 使用__new__()

import threadingLock = threading.Lock()# 加锁为了保证线程安全class Foo(object):    __isinstance = None    def __new__(cls, *args, **kwargs):        # 如果发现__isinstance 有值了直接返回,不进锁了        if not cls.__isinstance:            with Lock:                if not cls.__isinstance:                    cls.__isinstance =  super(Foo,cls).__new__(cls)        return cls.__isinstanceobj = Foo()obj2 = Foo()print(obj,obj2)

 

 

2. 模块导入

其实,Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。如果我们真的想要一个单例类,可以考虑这样做:

# mysingleton.pyclass My_Singleton(object):    def foo(self):        pass my_singleton = My_Singleton()

将上面的代码保存在文件 mysingleton.py 中,然后这样使用:  

from mysingleton import my_singleton my_singleton.foo()

  

3. 使用装饰器

基本思想为:

1、在装饰器中添加一个字典类型的自由变量_instance;

2、在闭包中判断类名是否存在于_instance中,如果不存在则创建一个类的事例,并讲其添加到字典中;如果存在则不进行实例化,直接返回字典中的实例;

def Singleton(cls):      _instance = {}      def _singleton(*args, **kargs):          if cls not in _instance:              _instance[cls] = cls(*args, **kargs)          return _instance[cls]      return _singleton    @Singleton  class A(object):      a = 1      def __init__(self, x = 0):          self.x = x      a1 = A(2)  a2 = A(3)  print id(a1)  print id(a2)  print a1.x  print a2.x      ''''' ---------------------------------------- 45838576 45838576 2 2 '''  

 

4. 使用元类

 

示例化一个类的时候,如果他有元类,先执行元类的__call__方法,cll方法的第一个参数就是子类,先执行子类的__new__,子类没有执行objects的__new__,实例化后执行初始化__init__ ,修改isinstance的值并返回

import threadingLock = threading.Lock()class Singleton(type):    def __call__(cls, *args, **kwargs):        if not hasattr(cls,"isinstance"):            with Lock:                if not hasattr(cls,"isinstance"):                    obj = cls.__new__(cls,*args,**kwargs)                    obj.__init__(*args,**kwargs)                    setattr(cls,"isinstance",obj)                return getattr(cls,"isinstance")        return getattr(cls,"isinstance")class Foo(object,metaclass=Singleton):    def __init__(self):        self.name = "zhou"obj = Foo()obj2 = Foo()print(obj,obj2)

 

 

5. 使用类方法的单例模式

加锁为类线程安全

import threadingimport timeclass Foo(object):    instance = None    lock = threading.Lock()    def __init__(self):        self.a1 = 1        self.a2 = 2        import time        import random        time.sleep(2)    @classmethod    def get_instance(cls,*args,**kwargs):        if not cls.instance:            with cls.lock:                if not cls.instance:                    obj = cls(*args,**kwargs)                    cls.instance = obj                return cls.instance        return cls.instancedef task():    obj = Foo.get_instance()    print(obj)import threadingfor i in range(5):    t = threading.Thread(target=task,)    t.start()time.sleep(10)# 实例化时调用get_instanceFoo.get_instance()

 

 

 

转载于:https://www.cnblogs.com/zhoujunhao/p/8471617.html

你可能感兴趣的文章
iOS-Get the NSString height in iOS 7
查看>>
对象调用成员的过程
查看>>
linux安装man中文手册并保留英文man手册
查看>>
SSH密码和秘钥认证原理
查看>>
现有‘abcdefghijkl’12个字符,将其所有的排列按字典序进行排序,给出任意一组排列,说出这租排列在所有排列中是第几小的...
查看>>
数据结构12——哈希
查看>>
云计算简介及总结
查看>>
提高ASP.NET网站性能的方法
查看>>
这几天学习Objective的笔记
查看>>
oracle REPLACE 函数 介绍
查看>>
mybatis动态SQL标签的用法
查看>>
学习extjs的布局
查看>>
java-swing模拟实现时钟效果
查看>>
java points[复习]
查看>>
在另一个线程中无法用((CMainFrame *)AfxGetMainWnd())
查看>>
Ignatius and the Princess IV
查看>>
BC#50 1003 The mook jong
查看>>
DEDECMS中,自增长标签
查看>>
JS学习之动态加载script和style样式
查看>>
python快速入门——进入数据挖掘你该有的基础知识
查看>>