单例模式的写法非常多,但常规型的单例模式就是这样写的,各种代码可能略有差异,但核心就是要搞清楚类属性 实例属性,就很容易写出来,原理完全一模一样。
如下:
源码:
class A(object): def __new__(cls, *args, **kwargs): if not hasattr(cls, ‘__inst‘): print(‘执行new‘) obj = super(A, cls).__new__(cls) setattr(cls, ‘__inst‘, obj) return obj else: return cls.__dict__[‘__inst‘] def __init__(self, x): print(‘执行init‘) self.x = x if __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 import wraps def singleton(cls): print cls instances = {} @wraps(cls) def getinstance(*args, **kw): if cls not in instances: instances[cls] = cls(*args, **kw) return instances[cls] return getinstance @singleton class MyClass(object): a = 1 m1=MyClass() m2=MyClass() print m1 is m2
原文地址:https://www.cnblogs.com/ydf0509/p/9463832.html
时间: 2024-10-03 00:55:06