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)
這樣裝飾器就可以處理不確定個參數的函數了。