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()
    return  inner

@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”

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章