python中的單例模式

單例模式(Singleton Pattern)是一種經常使用的軟件設計模式,該模式的主要目的是確保某一個類只有一個實例存在。當你但願在整個系統中,某個類只能出現一個實例時,單例對象就能派上用場。設計模式

好比,某個服務器程序的配置信息存放在一個文件中,客戶端經過一個 AppConfig 的類來讀取配置文件的信息。若是在程序運行期間,有不少地方都須要使用配置文件的內容,也就是說,不少地方都須要建立 AppConfig 對象的實例,這就致使系統中存在多個 AppConfig 的實例對象,而這樣會嚴重浪費內存資源,尤爲是在配置文件內容不少的狀況下。事實上,相似 AppConfig 這樣的類,咱們但願在程序運行期間只存在一個實例對象。服務器

在 Python 中,咱們能夠用多種方法來實現單例模式:app

  • 使用模塊
  • 使用 __new__
  • 使用裝飾器(decorator)
  • 使用元類(metaclass)

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]
functionstools.wraps

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
相關文章
相關標籤/搜索