单例模式的写法非常多,但常规型的单例模式就是这样写的,各种代码可能略有差异,但核心就是要搞清楚类属性 实例属性,就很容易写出来,原理完全一模一样。
如下:
源码:
classA(object):def __new__(cls, *args, **kwargs):if not hasattr(cls, ‘__inst‘):print(‘执行new‘)
obj= super(A, cls).__new__(cls)
setattr(cls,‘__inst‘, obj)returnobjelse:return cls.__dict__[‘__inst‘]def __init__(self, x):print(‘执行init‘)
self.x=xif __name__ == ‘__main__‘:
a1= A(1)print(‘a1.x‘, a1.x)
a2= A(2)print(‘a2.x‘, a2.x)print(‘a1.x‘, a1.x)
a3= A.__new__(A)#a3.__init__(3) # a3 = A(3) 实际是调用了new和init方法,此处屏蔽调用init
print(‘a3.x‘, a3.x)print(id(a1), id(a2), id(a3))
实例化了三个对象,执行结果可以猜猜:
可以发现,执行了一次new,但执行了两次init,这是在新式类下运行的,python3默认是新式类,不管有没有继承object。
如果是python2,且不继承object,实际上是只会打印执行一次init。所以这是py2和py3的又一个区别,经典类和新式类区别非常多,新式类的反射方法也与经典类有些不同。但一般文章只说新式类和经典类的区别只是广度优先和深度优先,误导。
3、终极目标就是使python3的实例也不多执行力一次init,(因为虽然单例模式能控制成是所有类的实例指向同一个对象,但有时候的单例模式初始化是建立一个io连接或者资源池,这样每次执行初始化浪费一些时间)
两种方法,一种是增加一个类属性做标志,在init方法中增加if判断
第二种是,不使用 a = A(xxxx),而使用a = A.__new__(A),因为a = A(xxxx),实际上是a = A.__new__(A),和a.__init__(xxx)
4、还有一种方式是使用装饰器,如果按照这个写法也不会执行多次init
#coding=utf8
from functools importwrapsdefsingleton(cls):printcls
instances={}
@wraps(cls)def getinstance(*args, **kw):if cls not ininstances:
instances[cls]= cls(*args, **kw)returninstances[cls]returngetinstance
@singletonclassMyClass(object):
a= 1m1=MyClass()
m2=MyClass()print m1 is m2
原文:https://www.cnblogs.com/ydf0509/p/9463832.html