python面向物件之裝飾器
裝飾器是什麼
裝飾器本質上是一個函式,該函式用來處理其他函式,它可以讓其他函式在不需要修改程式碼的前提下增加額外的功能,裝飾器的返回值也是一個函式物件。它經常用於有切面需求的場景,比如:插入日誌、效能測試、事務處理、快取、許可權校驗等應用場景。裝飾器是解決這類問題的絕佳設計,有了裝飾器,我們就可以抽離出大量與函式功能本身無關的雷同程式碼並繼續重用。概括的講,裝飾器的作用就是為已經存在的物件新增額外的功能。甚至,有人這樣說:"內褲可以用來遮羞,但是到了冬天沒法為我們防風禦寒,聰明的人發明了長褲,有了長褲以後就不會再冷了。裝飾器就是我們這裡說的長褲,在不影響內褲作用的前提下,給我們的身體提供了保暖的功效。"
為什麼需要裝飾器
先看一個簡單的例子
def test_one(): print("test_one")
現在有個需求,希望可以輸出函式的執行日誌,這時,有人會這樣實現:
def test_one(): print('test_one') print('test_one is running')
但是,如果有其他的函式需要這功能,那麼會出現很多的重複程式碼,為了減少程式碼的重複,我們需要建立一個專門的記錄日誌的函式,誰需要執行日誌,就把誰作為引數傳遞。
def print_log(func): print('函式正在執行中...') func() def test_one(): print("test_one") print_log(test_one)
按照上述程式碼將函式作為引數傳遞,需然可以實現功能,但是卻破壞了原有程式碼的邏輯結構。如果要求已經實現的函式,不能修改,只能擴充套件,即遵守“封閉開放”原則,那麼是不允許在函式內部進行修改。
裝飾器可以滿足上述需求。在python中,裝飾器的語法是已@開頭,下面,我們寫一個簡單的裝飾器。
def wrap(func): print('正在裝飾') def inner(): print("正在驗證許可權") func() returninner @wrap def test(): print("test") test()
下面我們來分析一下程式的執行過程:
1、當程式執行test()時,發現函式test()上面有裝飾器@wrap,所以會執行@wrap。@wrap等價與test=wrap(test),他可以拆分為兩步:
①執行wrap(test),將函式名test作為引數傳遞給wrap.在呼叫wrap函式的過程中,首先執行print語句,輸出“正在裝飾”,然後會將形參func執行test()函式體,並將inner()函式的引用返回給wrap(test),作為wrap(test)的返回值。
②將warp(test)的返回值賦給test,此時,test指向inner()函式,到此完成了函式test()的裝飾。
2、呼叫test()指向的函式。因為test指向的是inner()函式,所以此時,呼叫test()函式相當於呼叫inner()函式,輸出如下:
①輸出pirnt語句:“正在驗證許可權”
②呼叫func指向的函式,輸出“test”