在python中,咱們能夠用多種方法來實現單例模式:python
- 使用模塊函數
- 使用__new__spa
- 使用裝飾器code
- 使用元類(metaclass)對象
使用模塊blog
其實,python的模塊就是自然的單例模式,由於模塊在第一次導入時,會生成.pyc文件,當第二次導入時,就會直接加載.pyc文件,而不會再次執行模塊代碼。所以咱們只需把相關的函數和數據定義在一個模塊中,就能夠得到一個單例對象了。ip
# mysingle.py class MySingle:
def foo(self):
pass
sinleton = MySingle()
將上面的代碼保存在文件mysingle.py中,而後這樣使用:
from mysingle import sinleton
singleton.foo()
使用__new__get
爲了使類只能出現一個實例,咱們能夠使用__new__來控制實例的建立過程,代碼以下:it
使用裝飾器:class
咱們知道,裝飾器能夠動態的修改一個類或函數的功能。這裏,咱們也能夠使用裝飾器來裝飾某個類,使其只能生成一個實例:
def singleton(cls): instances = {} def getinstance(*args,**kwargs): if cls not in instances: instances[cls] = cls(*args,**kwargs) return instances[cls] return getinstance @singleton class MyClass: a = 1 c1 = MyClass() c2 = MyClass() print(c1 == c2) # True
在上面,咱們定義了一個裝飾器 ,它返回了一個內部函數 ,
該函數會判斷某個類是否在字典 中,若是不存在,則會將 做爲 key, 做爲 value 存到 中,
不然,直接返回 。
singletongetinstanceinstancesclscls(*args, **kw)instancesinstances[cls]
使用metaclass(元類)
元類能夠控制類的建立過程,它主要作三件事:
- 攔截類的建立
- 修改類的定義
- 返回修改後的類
使用元類實現單例模式:
class Singleton2(type): def __init__(self, *args, **kwargs): self.__instance = None super(Singleton2,self).__init__(*args, **kwargs) def __call__(self, *args, **kwargs): if self.__instance is None: self.__instance = super(Singleton2,self).__call__(*args, **kwargs) return self.__instance class Foo(object): __metaclass__ = Singleton2 #在代碼執行到這裏的時候,元類中的__new__方法和__init__方法其實已經被執行了,而不是在Foo實例化的時候執行。且僅會執行一次。 foo1 = Foo() foo2 = Foo() print (Foo.__dict__) #_Singleton__instance': <__main__.Foo object at 0x100c52f10> 存在一個私有屬性來保存屬性,而不會污染Foo類(其實仍是會污染,只是沒法直接經過__instance屬性訪問) print (foo1 is foo2) # True