研究了一下python的单利模式,简单地记录一下.
1.类和实例的创建过程
从创建类到初始化一个对象,简单地可以分为四个步骤:
(1)通过元类创建一个类,调用__new__完成类的创建(阶段A)
(2)初始化一个类,调用__init__,初始化一个类(阶段B)
(3)通过类创建一个对象,调用__new__(阶段D)
(4)初始化一个对象,调用__init__(阶段E)
图中阶段A,阶段B,阶段C是由元类完成的,在文件加载的时候,自动调用__new__和__init__,阶段E不是必须的.阶段D,阶段E是创建一个实例的过程,手动调用__new__和__init__.一般情况下,创建一个类只用实例化一个类,即调用__init__,而__new__的执行被隐藏了,主要是继承了父类的__new__方法
说完了类和实例的创建过程之后,考虑一下单例模式应该在这四个阶段中哪个阶段控制比较合适?
(1)阶段A:
创建一个类的过程,也就是说类的创建并未完成.单例是建立实例上,实例的创建又是建立在类上面的,这个阶段类还没有创建,也就不太适合
(2)阶段B:
实例化一个类,这个阶段类也创建完成了,似乎有机会控制实例的个数
(3)阶段D:
类的创建和实例化完成了,开始创建一个实例,但还未完成,也可以控制实例的个数
(4)阶段E:
这个阶段,对象已经建立了,每一次实例化一个类时,对象已经建立了,控制不了实例的个数.
简单说,阶段A (创建类的过程)类没有建立,不宜控制实例数量.阶段E(类实例化的过程)实例已经创建,控制不了实例数量.在阶段B(实例化一个类)和阶段D(创建一个实例)比较容易控制实例的数量,也就最利于实现单例模式.
2.实现单例模式
(1)阶段B(实例化一个类)
主要是通过建立元类进行控制:
# B阶段
class Singleton_C(type):
def __init__(self, *args, **kwargs):
self.__instance = None
super(Singleton_C, self).__init__(*args, **kwargs)
def __call__(self, *args, **kwargs):
if self.__instance is None:
self.__instance = super(Singleton_C, self).__call__(*args, **kwargs)
return self.__instance
else:
return self.__instance
class C:
__metaclass__ = Singleton_C
def __init__(self):
print ‘I am C‘
a = C()
b = C()
print a is b # True
(2)阶段D(创建实例的过程)
# D阶段
class Singleton_D(object):
‘‘‘实例存储在Sigleton_B类的字典中‘‘‘
def __new__(cls, *args, **kwargs):
if not hasattr(cls, ‘_instance‘):
cls._instance = super(Singleton_B, cls).__new__(cls, *args, **kwargs)
return cls._instance
# 先继承其他类时, 会导致单例模式失效
class D(Singleton_D):
def __init__(self):
print ‘I am D‘
a = D()
b = D()
print a is b # True
(3)阶段D(创建实例的过程) --- 一个伪单例模式
每一次实现的对象不同,但共用变量
# D阶段
class Singleton_D1(object):
_store = {}
def __new__(cls, *args, **kwargs):
obj = super(Singleton_B1, cls).__new__(cls, *args, **kwargs)
print cls, obj, id(cls._store), id(obj._store), id(Singleton_B1._store)
obj.__dict__ = cls._store
return obj
# 先继承其他类时, 会导致单例模式失效
class F(Singleton_D1):
def __init__(self, name):
self.name = name
f1 = F(‘python‘)
f2 = F(‘singleton‘)
print f1 is f2 # False
(4)装饰器
def singleton(cls):
obj = {}
def wrapper(*args, **kwargs):
if cls not in obj:
obj[cls] = cls(*args, **kwargs)
return obj[cls]
return wrapper
@singleton
class Foo(object):
pass
f1 = Foo()
f2 = Foo()
print f1 is f2 # True
原文:https://www.cnblogs.com/chimpan/p/9410779.html