1. 程式人生 > >python 使用裝飾器實現單例模式

python 使用裝飾器實現單例模式

1、裝飾器

python中一切皆物件,同樣函式也是一個物件。函式物件有一個__name__屬性,可以檢視函式的名字。
 

def demo():
    print("xxx")

print(demo.__name__)

output:
 demo

假設我們要增強函式demod的功能,比如在函式執行前自動列印日誌,但又不希望改變demo()函式的定義,此時就用到了裝飾器。
這種在程式碼執行期間動態增加功能的方式,稱為裝飾器(decorator)。Python的decorator可以用函式實現,也可以用類實現。

def log(func):
    def wrapper(*args, **kw):
        print 'call %s():' % func.__name__
        return func(*args, **kw)
    return wrapper
@log
def demo():
    print("xxx")

demo()


output:
call demo():
xxx

 

2、單例模式

單例模式(Singleton Pattern)是一種常用的軟體設計模式,該模式的主要目的是確保某個類只有一個例項存在。如某個程式的配置檔案,程式可能通過一個Settings的類來讀取配置檔案的資訊。如果在程式執行期間有很多地方需要用到配置檔案的內容,也就是很多地方需要建立Settings的例項,這就導致刺痛中存在多個Settings的例項物件,這樣會嚴重浪費記憶體資源。類似於這種情況,我們希望程式執行期間只存在一個例項物件。

 

3、裝飾器來實現單例模式:

from functools import wraps

def Singleton(cls):
    _instance = {}
    @wraps(cls)
    def _singleton(*args, **kargs):
        if cls not in _instance:
            _instance[cls] = cls(*args, **kargs)
        return _instance[cls]

    return _singleton

@Singleton
class Settings():
    """Docstring"""
    def __init__(self):
        self.a = "xxx"
        self.b = "xxx"


settings = Settings()
print(settings.a)
print(Settings.__name__)
print(Settings.__doc__)

output:
xxx
Settings
Docstring

程式碼中@wraps的作用:Python裝飾器(decorator)在實現的時候,被裝飾後的函式其實已經是另外一個函數了(函式名等函式屬性會發生改變),為了不影響,Python的functools包中提供了一個叫wraps的decorator來消除這樣的副作用。寫一個decorator的時候,最好在實現之前加上functools的wrap,它能保留原有函式的名稱和docstring。