網上最長見的版本:
1 class Singleton(object): 2 __instance=None 3 def__init__(self): 4 pass 5 def__new__(cls,*args,**kwd): 6 if Singleton.__instance is None: 7 Singleton.__instance=object.__new__(cls,*args,**kwd) 8 return Singleton.__instance
坑1:每次實例化時,__init__()都會執行一次
原因:python每次實力化一個類先調用__new__方法,再調用__init__方法。在__new__方法中,在不讓子類有感知的情況下,無法跳過該機制
坑2:該類無法繼承,如果有多個類繼承了該基類,那么每次實例化不同的類得到的結果都是第一次實例化時得到的類
原因:__instance作為Singleton這個類的類變量存在,當第一次實例化該類的子類時,__instance被設置為實例化的結果,之后實例化每個子類時,在__new__函數中檢測到該變量已設置就不會再去實例化,所以該值也就不會變化。
改進:
class Singleton(object): def __new__(cls, *args, **kwargs): if not hasattr(cls, '__instance'): print('in new') cls.__instance = object.__new__(cls, *args, **kwargs) cls.__instance.__Singleton_Init__(*args, **kwargs) return cls.__instance def __Singleton_Init__(self): print("__Singleton_Init__")
填坑1:該類規定子類的初始化函數是__Singleton_Init__,這樣就可以在__new__方法中控制初始化方法的調用
填坑2:__new__方法的cls參數是最上的層子類,判斷cls.__instance是否被設置就是在判斷各個子類是否有__instance成員變量,這樣就可以愉快的繼承了
再挖個坑:if not hasattr(cls, '__instance'),為什么這里可以檢查cls的“私有成員”
一個例子:
# -*- coding: utf-8 -*- class Singleton(object): def __new__(cls, *args, **kwargs): if not hasattr(cls, '__instance'): print('before new') print(cls) cls.__instance = object.__new__(cls, *args, **kwargs) print('after new') cls.__instance.__Singleton_Init__(*args, **kwargs) return cls.__instance def __init__(self): print("__init__") def __Singleton_Init__(self): print("__Singleton_Init__") class BB(Singleton): pass class CC(Singleton): pass c = CC() c1 = CC() b=BB() b.a=2 c.a=3 print(id(c), id(c1)) print(b.a, c.a)