def singleton(cls):
def get_instance(*args, **kwargs):
if not hasattr(cls, "_instance"):
cls._instance = cls(*args, **kwargs)
return cls._instance
return get_instance
class singleton(type):
def __call__(cls, *args, **kwargs):
if not hasattr(cls, "__instance"):
cls.__instance = super().__call__(*args, **kwargs)
return cls.__instance
這個地方,我看了好多部落格,都是cls._instance = super().__new__(cls, *args, **kwargs)
但是呢, 這是錯誤的!!!
因為singleton的超類是object,而object呼叫__new__方法的時候是不需要任何引數的。
class singleton:
def __new__(cls, *args, **kwargs):
if not hasattr(cls, "_instance"):
# 注意,這個地方通過超類來獲取例項的時候,傳遞的引數是超類需要的
# 超類不需要的是不能傳遞的
# 而這個地方singleton的超類是object,因此是不需要任何引數,除了cls的
cls._instance = super().__new__(cls)
return cls._instance
點評:這三個方法實現**模式,本質上是一致的。都是在建立新的例項的時候,會對該類是否已經建立了例項做判斷。如果沒有例項,則產生新的例項;如果已經有,則略過,返回舊的例項。
但是呢,通過繼承實現的單例模式是有點突出的。因為它跟其他方式有點不同,它是通過new方法的改造實現的。如果之前有就返回之前的例項;如果沒有,就建立新的例項。
需要知道的是,建立例項,有兩個過程,乙個是new方法建立例項物件,然後再由init方法初始化例項物件。
也就是繼承那種方式,new返回的例項,會再通過init方法初始化。
也就是,其屬性會得到更新。
例子如下:
class singleton:
def __new__(cls, *args, **kwargs):
if not hasattr(cls, "_instance"):
cls._instance = super().__new__(cls)
return cls._instance
class a(singleton):
def __init__(self, a, b):
self.a = a
self.b = b
def __str__(self):
return "a is " + str(self.a) + "; b is " + str(self.b)
a1 = a(1, 2)
print(a1)
a2 = a(2, 3)
print(a2)
print("a1 is a2 => ", a1 is a2)
結果是這樣的
a is 1; b is 2
a is 2; b is 3
a1 is a2 => true
可以看見,例項的屬性是得到更新的。。。。。
而其他兩種方式中,都是在new方法之前對該類是否已有例項進行判斷。
python實現單例模式
最近在寫乙個連線池,而連線池管理類不可避免的需要使用單例來保證所有使用者在取得連線時取到的一定是同乙個管理物件。故將此模式取來研究一番。保證乙個類僅有乙個例項,並提供乙個訪問它的全域性訪問點 設計模式 單例模式是全域性只有乙個訪問點,故對於乙個類來說,任何例項化後訪問到的都應該是同樣的物件。而也有另...
Python 實現單例模式
encoding utf 8 print 方法1 方法1,實現 new 方法 並在將乙個類的例項繫結到類變數 instance上,如果cls.instance為none說明該類還沒有例項化過,例項化該類,並返回 如果cls.instance不為none,直接返回cls.instance class ...
python實現單例模式
單例模式,簡單來說,就是乙個類只能有乙個例項,並且能夠自行例項化向整個系統提供。例如檔案系統和任務管理器等。由此可見,單例模式的要點有三個 1.乙個類只能有乙個例項 2.它必須自行建立這個例項 3.它必須自行向整個系統提供這個例項 在python實現單例模式的方法總結起來有四種及其對應 如下 1.魔...