Python 单例模式的几种实现方式

单例模式的几种实现方式
1._new_(cls, *args, **kw) 方法实现
class Singleton(object):
    """
    构造方法 new 方法至少需要一个 cls 参数,实例化时,解释器会自动填入;
    若 _instance = {}, 则
    if cls not in cls._instance:
    	cls._instance[cls] = object.__new__(cls, *args, **kw)
    不要 = cls(), cls() 就是调用的 cls.__new__(),会报【超出最大递归深度】错误;
    """
    _instance = None  # 新建一个类属性:需要使用类名前缀来访问
    
    def __new__(cls, *args, **kw):  # 创建实例时,判断是否已经存在,存在,返回,不存在,创建
        if cls._instance is None:
            cls._instance = object.__new__(cls, *args, **kw)  # 不要调用自己的,会无限递归; cls() 就是调用的 cls.__new__()
            
        return cls._instance  # new 方法中返回实例对象
        
    def __init__(self):
        pass
    
sing1 = Singleton()
sing2 = Singleton()
sing1 is sing2  # true
2.函数装饰器实现:实例化前先调用这个装饰器返回的 inner() 函数,再返回实例
def singleton(cls):  # 自定义装饰器, 函数中再嵌套一个函数, 并返回嵌套函数名
    """
    用不可变的 类地址 作为键,其 实例 作为值,
    每次创造实例时,首先判断该类是否存在实例,存在,直接返回该实例即可,否则新建一个实例并存放在字典中.
	
    不要 _instance = None, 否则 inner 函数中有赋值,_instance 只会在函数作用域搜索,判断时会报错;
	"""
    _instance = {}  # 新建空字典
    
    def inner():  # 判断是否已有实例,如无,则新建一个实例并返回
        if cls not in _instance:
            _instance[cls] = cls()

        return _instance[cls]  # 返回的是实例对象,别搞蒙了
    
    return inner

@singleton
class Cls():
    def __init__(self):
        pass  # 可以照常添加属性和方法
    
cls1 = Cls()
cls2 = Cls()
cls1 is cls2  # True
3.类装饰器实现
"""
启用 __call__(self) 函数
"""
class Singleton(object):  # 自定义类装饰器
    def __init__(self, cls):  # 赋初值
        self.cls = cls
        self.instance = {}
        
    def __call__(self):  # 调用类装饰器时,判断是否已存在
        if self.cls not in self.instance:
            self.instance[self.cls] = self.cls()
            
        return self.instance[self.cls]  # 返回实例对象

@Singleton
class Cls(object):
    def __init__(self):
        pass
    
cls4 = Cls()
cls5 = Cls()
cls4 is cls5  # True
4.metaless 元类实现
"""
	元类->类->实例,简单来说,就是类是由元类创建的,type 是内置的元类,也可以自定义元类;
	下面两条语句会创建相同的 type 对象:
		class X:
			a = 1

		X = type('X', (object,), dict(a=1))  # 动态的创建类对象,dict 也可以直接用 {'a':1, 'func_name': func_name}
"""
class Singleton4(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton4, cls).__call__(*args, **kwargs)

        return cls._instances[cls]

class Cls4(metaclass=Singleton4):
    pass

cls1 = Cls4()
cls2 = Cls4()
print(id(cls1) == id(cls2))
上一篇:Python 绑定与非绑定方法


下一篇:python中cls关键字