zhangpan 2019-10-24
# 方法一,装饰器 from functools import wraps def single_instance(cls): """装饰器实现单例模式,装饰器相当于把类给包了起来,强制返回一个对象""" _instance = None @wraps(cls) def wrapper(*args, **kwargs): nonlocal _instance if _instance is None: _instance = cls(*args, **kwargs) return _instance return wrapper @single_instance class Test1: def __init__(self, name): self.name = name print("Test init..., name=%s" % self.name) # 方法二 __new__方法 class Test2: _instance = None def __init__(self, name): self.name = name print("Test2 init..., name=%s" % self.name) def __new__(cls, *args, **kwargs): """__new__主要做的是给实例分配空间,__init__则是在该空间上进行初始化,既然是单例模式,那么空间地址肯定一样,这里做限制""" print(‘__new__, args=‘, args, ‘,kwargs=‘, kwargs) if cls._instance is None: cls._instance = super().__new__(cls) return cls._instance # 方法三 元类 class SingleType(type): """ 普通类相当于是元类的实例,所以在类完成定义时其实是调用元类的__init__方法,而生成类的实例,如 Test(‘AIF‘)则是调用元类的__call__方法 这个跟普通类和实例的关系其实是一样的。如 t = Test(‘AIF‘), 生成t会调用Test的__init__方法,而t()则会调用Test的__call__方法 """ def __init__(self, *args, **kwargs): self._instance = None super().__init__(*args, **kwargs) def __call__(self, *args, **kwargs): if self._instance is None: self._instance = super().__call__(*args, **kwargs) return self._instance class Test3(metaclass=SingleType): def __init__(self, name): self.name = name print("Test3 init..., name=%s" % self.name) if __name__ == ‘__main__‘: """测试,Test1, Test2, Test3""" a = Test3(‘AIF‘) b = Test3(‘AIF333‘) print(‘a=b is %s, id(a)=%s, id(b)=%s‘ % (a is b, id(a), id(b))) print(‘a.name=%s, b.name=%s‘ % (a.name, b.name))