Python 裝飾器初探
阿新 • • 發佈:2018-12-29
Python 裝飾器初探
在談及Python的時候,裝飾器一直就是道繞不過去的坎。面試的時候,也經常會被問及裝飾器的相關知識。總感覺自己的理解很淺顯,不夠深刻。是時候做出改變,對Python的裝飾器做個全面的瞭解了。
1. 函式裝飾器
直接上程式碼,看看裝飾器到底幹了些什麼?
from functools import wraps import time def time_cost(func): @wraps(func) def f(*args, **kwargs): start_time = time.time() func(*args, **kwargs) end_time = time.time() print(end_time - start_time) return f @time_cost def test(*args, **kwargs): time.sleep(1.0) if __name__ == "__main__": test()
上面的Python程式碼,執行後,會給出test函式的執行時間。程式碼的執行順序大概如下,首先是將test作為值傳遞給time_cost函式,返回函式f,然後再呼叫f,這是帶有time_cost裝飾器的test函式的大致執行過程。
從中,不難看出,即使不使用裝飾器符號,我們利用Python的語言特性,也能達成上述目的。用裝飾器符號的好處是簡化了程式碼,增加了程式碼的可讀性。
這是一段非常簡單的對函式使用裝飾器的Python程式碼。等等,@wraps(func)
是什麼鬼?悄悄幹了什麼哇?
我們稍微修改下上式的程式碼,結果如下:
from functools import wraps import time def time_cost(func): def f(*args, **kwargs): start_time = time.time() func(*args, **kwargs) end_time = time.time() print(end_time - start_time) print('hello world') return f @time_cost def test(*args, **kwargs): time.sleep(1.0) if __name__ == "__main__": print(test.__name__)
發現輸出了hello world
,同時輸出test.__name__
,居然變成了f
,並不是我們預期的test
。根據這樣的輸出結果,我們不難得出,其實被裝飾器time_cost
修飾過的函式test本質上已經等同於time_cost(test)
,此時訪問test.__name__
實際上訪問的是time_cost(test).__name__
,得到的當然就是f
啦。當我們加上@wraps(func)
,此時test.__name__
變成了test
。