zoukankan      html  css  js  c++  java
  • 聊一聊python的单例模式

    单例模式

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

    四种方法:

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

    1. 使用__new__()

    import threading
    
    Lock = 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.__isinstance
    
    
    obj = Foo()
    obj2 = Foo()
    
    print(obj,obj2)

    2. 模块导入

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

    # mysingleton.py
    class 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 threading
    
    Lock = 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 threading
    import time
    
    class 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.instance
    def task():
        obj = Foo.get_instance()
        print(obj)
    
    import threading
    for i in range(5):
        t = threading.Thread(target=task,)
        t.start()
    
    time.sleep(10)
    # 实例化时调用get_instance
    Foo.get_instance()

     

  • 相关阅读:
    leetcode231 2的幂 leetcode342 4的幂 leetcode326 3的幂
    leetcode300. Longest Increasing Subsequence 最长递增子序列 、674. Longest Continuous Increasing Subsequence
    leetcode64. Minimum Path Sum
    leetcode 20 括号匹配
    算法题待做
    leetcode 121. Best Time to Buy and Sell Stock 、122.Best Time to Buy and Sell Stock II 、309. Best Time to Buy and Sell Stock with Cooldown 、714. Best Time to Buy and Sell Stock with Transaction Fee
    rand7生成rand10,rand1生成rand6,rand2生成rand5(包含了rand2生成rand3)
    依图
    leetcode 1.Two Sum 、167. Two Sum II
    从分类,排序,top-k多个方面对推荐算法稳定性的评价
  • 原文地址:https://www.cnblogs.com/zhoujunhao/p/8471617.html
Copyright © 2011-2022 走看看