NO IMAGE

前言

裝飾器是一種著名的設計模式,允許我們動態的為一個物件來新增一些額外的功能而無需去修改它所在的類或者是建立新類。python中的函式也是一種物件,下面用幾個函式例項來說明python中的裝飾器。

需求

首先從最簡單的開始,假設我們有如下的函式:

def my_func():  
print 'do something'

現在的需求是需要在每次執行該條語句之前輸出日誌start dosomething,方便以後分析,最直觀的方法就是就是修改函式體在其中增加日誌輸出語句或者在程式中每處呼叫的my_func的地方增加輸出語句,這兩個方法明顯都是不可取的,在這樣的場合我們需要裝飾器。

簡單實現

實現上面需求的最簡單的python裝飾器如下:

def decorator(func):
def log():
print 'start to do something'
func();
return log 
@decorator  
def my_func():
print 'do something'

現在我們執行 my_func(),程式輸出如下:

start to do something
do something

  可以看見,原來的my_func函式擁有了新的功能,這就是裝飾器的作用,動態的給現有的物件增加額外的功能。程式碼中的decorator函式就是裝飾函式,它接收一個物件,修飾這個物件,並返回一個增強了的新物件,注意python中一切皆物件,函式也是物件。而@decorator這一句則是python中的一個語法糖,它告訴我們這裡使用了裝飾器,用decorator函式來裝飾my_func,在上面程式碼中函式定義前加上@decorator這一句其實等效於在函式定以後加上 my_func = decorator(my_func),只是@的符號使我們能夠更直觀的一眼看出這裡使用了裝飾器。這裡我們實現了一個最簡單的裝飾器,通過這個簡單的例子我們對裝飾器有了一個大概的概念,舉個通俗的例子,就好比手機貼膜,我們希望自己的手機螢幕能夠防指紋,這對應於我們的需求,需要給手機增加新的功能,沒有人會去手機店把自己的手機原有的螢幕拆下來,換上新的防指紋的螢幕,更好的辦法是去貼膜的地方貼一張防指紋膜,對應於程式也是,有時候我們需要動態的給一個物件增加新功能,修改生成物件的類往往是不可取的,這時候就需要使用裝飾器模式,上面程式中的的my_func函式就相當於我們的手機,decorator函式就相當於貼膜店,my_func經過decorator的處理後增加了日誌輸出功能就相當於給手機貼了層膜,在不改動my_func函式實現的情況下我們給其增加了新功能,這點是非常重要的,也是裝飾器最大的用處,尤其是在其他語言中,my_func函式或者要修改物件的具體實現我們並不一定能夠知道,想要修改也無從下手的情況下。
  有了簡單概念後,下一節將會繼續介紹帶引數的裝飾器等稍微複雜的情況