分類目錄:《系統學習Python》總目錄
有趣的是,這里如果能使用nonlocal
語句(僅在Python3.X中可用)來改變外層作用域名稱,我們在這里可以編寫一個自包含程度更高的解決方案一一一下面的替代方案為每個類使用了一個外層作用域,而不是為每個類使用一個全局表入口,并實現了同樣的效果。雖然這工作起來相同,但是它不依賴裝飾器外的全局作用域中的變量名(注意這里的None
檢查可以使用is
而不是==
,但是無論采用哪種方式,它們實現的功能都是一個很平常的測試):
def singleton(aClass):instances = Nonedef onCall(*args, **kwargs):nonlocal instancesif instances is None:instances = aClass(*args, **kwargs)return instancesreturn onCall
在Python3.X或Python2.X(2.6及之后的)版本中,我們也可以用函數屬性或類編寫一個自包含的解決方案。下面代碼中的第一段編寫了前者,它利用了每個裝飾都會有一個onCall
函數的事實一一對象命名空間充當了與外層作用域相同的角色。下面代碼中的第二段為每次裝飾使用一個實例,而不是使用一個外層作用域、函數對象或全局表。實際上,第二段代碼依賴于相同的編程模式,隨后我們會看到這是一個常見的裝飾器類錯誤。這里我們只想要一個實例,但情況并不經常是這樣:
def singleton(aClass):def onCall(*args, **kwargs):onCall.instances is None:onCall.instances = aClass(*args, **kwargs)return instancesonCall.instances = Nonereturn onCallclass singleton:def __init__(self, aCkass):self.aCkass = aCkassself.instances = Nonedef __call__(self, *args, **kwargs):if self.instances is None:self.instances = self.aCkass(*args, **kwargs)return self.instances
參考文獻:
[1] Mark Lutz. Python學習手冊[M]. 機械工業出版社, 2018.