python裝飾器的學習

最近在學習python的過程中看到一些代碼中在開頭頻頻出現@符號,例如下代碼所示:
DEBUG = True

def print_args(funcA):
    def funcB(a, b):
        if DEBUG:
            print(a, b)
    return funcB

@print_args
def make_list(a, b):
    return [a, b]

make_list(1, 2)

這樣的結構其實是python中的裝飾器,裝飾器的本質其實很簡單:函數。

在python中函數實際上就是一個特殊的變量,函數可以作爲另一個函數的參數,可以作爲另一個函數的返回值,同時函數還可以使用外層空間的變量。

函數在這樣的三個特性下,裝飾器就是:以函數爲參數,並返回一個函數的函數。換句話說,裝飾器就是一個特殊的函數,函數A作爲參數輸入,裝飾器經過處理返回函數B,這裏裝飾器的作用就是對輸入函數進行加強和修改。

以上面的代碼爲例:print_args()就是一個裝飾器,在代碼中用@調用,funcA作爲輸入參數,funcB是裝飾器的返回參數。funcA在這裏只構建一個list,這時裝飾器對funcA進行功能添加,其返回的funcB增加了打印該list的功能。


如果裝飾器處理的函數參數個數不確定怎麼辦,這裏也有解決的辦法:

在函數中,參數分爲位置參數和關鍵字參數,位置參數傳遞順序不能變,關鍵字參數位置可以變。如下函數所示:

def function(a, b, c, d=2, e=True):
    pass

a、b、c是位置參數,傳參順序不能改變,d、e是關鍵字參數,傳參順序可以改變。

所以可以這樣定義函數參數:

def function(*args,**kwargs):
    pass

args是元組:(a, b, c),kwargs是字典:{"d": 2, "e": True}。

這樣定義就可以傳遞未知個數參數。

那麼裝飾器可以這樣寫:

DEBUG = True

def print_args(funcA):
    def funcB(*pos_args, **keyword_args):
        if DEBUG:
            print(pos_args, keyword_args)
    return funcB

@print_args
def make_list(a, b):
    return [a, b]

@print_args
def add(a, b, c=3):
    return a + b + c

make_list(1, 2)
add(1, 2, 3)

這樣裝飾器就可以處理不確定個參數的函數了。

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