单例模式
单例模式,很好理解,一个类就一个实例
方法一:装饰器实现
在装饰器里维护一个字典,缓存所有的单例类,只要单例不存在就创建,已经存在直接返回实例对象
def singleton(cls): instances = {} def wrapper(*args,**kwargs): if cls not in instances: instances[cls] = cls(*args,**kwargs) return instances[cls] return wrapper @singleton class Foo: pass foo1 = Foo() foo2 = Foo() print(foo1 is foo2)
方法二:__new__方法
实例化对象其实是在__new__方法里,而__init__只做初始化,所以我们重写基类的__new__方法,保证只有一个实例
class Singleton: def __new__(cls, *args, **kwargs): if not hasattr(cls,'_instance'): cls._instance = super(Singleton,cls).__new__(cls,*args,**kwargs) return cls._instance class Foo(Singleton): pass foo1 = Foo() foo2 = Foo() print(foo1 is foo2)
方法三:元类
元类是用于创建类对象的类,类对象创建实例对象时一定会调用__call__方法,因此在调用__call__时候保证事中值创建一个实例即可,type是python中的类
class Singleton(type): def __call__(cls, *args, **kwargs): if not hasattr(cls, '_instance'): cls._instance = super(Singleton, cls).__call__(*args, **kwargs) return cls._instance class Foo(metaclass=Singleton): pass foo1 = Foo() foo2 = Foo() print(foo1 is foo2)
方法四:python模块导入时,只执行一次
这个是python独有的特性,在django加载admin模块时,用的就是这种方法实现单例模式
singleton.py
class Foo(object): def xx(self): print('xx') foo = Foo()
from singleton import foo foo.xx() from singleton import foo as foo2 foo2.xx() print(id(foo)) print(id(foo2))
能想到的应用场景:数据库的连接池,只要一份即可