聊一聊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()

 

原文地址:https://www.cnblogs.com/zhoujunhao/p/8471617.html