標籤:ret 不同 串連 bsp span png round UNC att
單例模式的寫法非常多,但常規型的單例模式就是這樣寫的,各種代碼可能略有差異,但核心就是要搞清楚類屬性 執行個體屬性,就很容易寫出來,原理完全一模一樣。
如下:
源碼:
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 = 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=utf8from functools import wrapsdef 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@singletonclass MyClass(object): a = 1m1=MyClass()m2=MyClass()print m1 is m2
python單例模式控製成只初始化一次,常規型的python單例模式在新式類和經典類中的區別。