單例模式(Singleton Pattern)是一種經常使用的軟件設計模式,該模式的主要目的是確保某一個類只有一個實例存在。當你但願在整個系統中,某個類只能出現一個實例時,單例對象就能派上用場。設計模式
好比,某個服務器程序的配置信息存放在一個文件中,客戶端經過一個 AppConfig 的類來讀取配置文件的信息。若是在程序運行期間,有不少地方都須要使用配置文件的內容,也就是說,不少地方都須要建立 AppConfig 對象的實例,這就致使系統中存在多個 AppConfig 的實例對象,而這樣會嚴重浪費內存資源,尤爲是在配置文件內容不少的狀況下。事實上,相似 AppConfig 這樣的類,咱們但願在程序運行期間只存在一個實例對象。服務器
在 Python 中,咱們能夠用多種方法來實現單例模式:app
__new__
1、模塊:ide
其實,Python 的模塊就是自然的單例模式,由於模塊在第一次導入時,會生成 .pyc
文件,當第二次導入時,就會直接加載 .pyc
文件,而不會再次執行模塊代碼。所以,咱們只需把相關的函數和數據定義在一個模塊中,就能夠得到一個單例對象了函數
# mysingleton.py class My_Singleton(object): def foo(self): pass my_singleton = My_Singleton()
使用:spa
from mysingleton import my_singleton my_singleton.foo()
2、使用 __new__
設計
__new__方法接受的參數雖然也是和__init__同樣,但__init__是在類實例建立以後調用,而 __new__方法正是建立這個類實例的方法。code
class Singleton(object): _instance = None def __new__(cls, *args, **kw): if not cls._instance: cls._instance = super(Singleton, cls).__new__(cls, *args, **kw) return cls._instance class MyClass(Singleton): a = 1 class Singleton(object): def __new__(cls): # 關鍵在於這,每一次實例化的時候,咱們都只會返回這同一個instance對象 if not hasattr(cls, 'instance'): cls.instance = super(Singleton, cls).__new__(cls) return cls.instance obj1 = Singleton() obj2 = Singleton() obj1.attr1 = 'value1' print obj1.attr1, obj2.attr1 print obj1 is obj2
在上面的代碼中,咱們將類的實例和一個類變量 _instance
關聯起來,若是 cls._instance
爲 None 則建立實例,不然直接返回 cls._instance
對象
3、使用裝飾器blog
from functools import wraps def singleton(cls): instances = {} @wraps(cls) def getinstance(*args, **kw): if cls not in instances: instances[cls] = cls(*args, **kw) return instances[cls] return getinstance @singleton class MyClass(object): a = 1
注:functools.wraps 則能夠將原函數對象的指定屬性複製給包裝函數對象, 默認有 __module__、__name__、__doc__,或者經過參數選擇
#不加wraps #coding=utf-8 # -*- coding=utf-8 -*- from functools import wraps def my_decorator(func): def wrapper(*args, **kwargs): '''''decorator''' print('Calling decorated function...') return func(*args, **kwargs) return wrapper @my_decorator def example(): """Docstring""" print('Called example function') print(example.__name__, example.__doc__) #結果:('wrapper', 'decorator') [Finished in 0.2s] #加wraps #coding=utf-8 # -*- coding=utf-8 -*- from functools import wraps def my_decorator(func): @wraps(func) def wrapper(*args, **kwargs): '''''decorator''' print('Calling decorated function...') return func(*args, **kwargs) return wrapper @my_decorator def example(): """Docstring""" print('Called example function') print(example.__name__, example.__doc__) 執行結果: ('example', 'Docstring') [Finished in 0.5s]
4、使用 metaclass
元類(metaclass)能夠控制類的建立過程,它主要作三件事:
class Singleton(type): _instances = {} def __call__(cls, *args, **kwargs): if cls not in cls._instances: cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) return cls._instances[cls] # Python2 class MyClass(object): __metaclass__ = Singleton # Python3 # class MyClass(metaclass=Singleton): # pass