初識Python裝飾器

任平生78發表於2017-06-20

python中,一切皆物件。做為物件導向開發中非常重要的一個環節,函式有著無可替代的作用。

函式可以作為物件賦值給一個變數,可以作為元素新增到集合物件中,可以作為引數值傳遞給其它函式,還可以當做函式的返回值被引用。

在現代軟體開發之中,有一個非常重要的原則,那就是****開放封閉原則****。

所謂****開放封閉原則****就是軟體實體應該****對擴充套件開放,而對修改封閉****。
開放封閉原則是所有物件導向原則的核心。

軟體設計本身所追求的目標就是封裝變化,降低耦合,而開放封閉原則正是對這一目標的最直接體現。 
開放封閉原則主要體現在兩個方面:
對擴充套件開放,意味著有新的需求或變化時,可以對現有程式碼進行擴充套件,以適應新的情況。
對修改封閉,意味著類一旦設計完成,就可以獨立其工作,而不要對類盡任何修改。 

為什麼要用到開放封閉原則呢?
軟體需求總是變化的,世界上沒有一個軟體的是不變的,因此對軟體設計人員來說,必須在不需要對原有軟體程式碼進行修改的情況下,實現靈活的系統擴充套件。  
如何做到對擴充套件開放,對修改封閉呢?
在python中,有一個很好的設計,那就是裝飾器。裝飾器的作用就是為已經存在的函式物件新增額外的功能     

裝飾器本質上是一個Python函式,可以是任意可呼叫物件,被裝飾物件也可以是任意可呼叫物件。

裝飾器的功能是:
在不修改被裝飾器物件原始碼以及被裝飾物件的呼叫方式的前提下,為被裝飾物件新增新功能

例如:

import time
def index():
    time.sleep(3)
    print("Welcome to index page")

index() 

結果會列印”****Welcome to index page****”這句話。那麼,假如現在我想為這個函式新增一個統計這段程式執行時間的功能,在符合開放封閉的前提下怎麼實現呢?
用裝飾器就可以實現了。

import time
def timmer(func):
    def wrapper():
        start_time=time.time()
        func()
        stop_time=time.time()
        print("The page run time is %s"%(stop_time-start_time))
    return wrapper

@timmer
def index():
    time.sleep(3)
    print("Welcome to index page")

index() 

執行結果如下:

Welcome to index page
The page run time is 3.000171422958374

在這段程式碼裡,在****index****函式的上面一行的那個****@timmer****就是裝飾器的專有語法,其呼叫方式等同於:****index=timmer(index)****。
程式執行步驟:

1.程式執行index函式,此時相當於執行index=timmer(index),把index函式作為一個引數傳遞給timmer這個函式。
2.呼叫timmer函式時,就相當於是在呼叫timmer函式的內部函式wrapper。
3.index作為timmer外層函式的引數,在wrapper這個內部函式的裡面也在呼叫。
4.在wrapper函式呼叫完成後,執行的結果又返回給wrapper函式,此時相當於把index函式,以及列印程式執行時間的功能執行的結果返回給timmer這個函式。
5.如前所述,timmer函式的執行結果也就等同於返回給index函式,這樣就完成了裝飾器的呼叫過程。

在這段程式碼裡,原有的程式就是index函式部分程式碼未做任何修改,index函式的呼叫方式也未做任何改變,統計程式的執行時間的功能也已經新增完成,這裡就使用了裝飾器的功能。


相關文章