最近幾周,陸續收到幾位讀者關于裝飾器使用的提問,今天統一回複。
1 問題大概問題是這樣,想要自定義一個Python裝飾器,問我這樣寫裝飾器行不行?如果不行,那又是為什麼?
import datetimeimport timedef print_time(g):def f:print('開始執行時間')print(datetime.datetime.today)gprint('結束時間')print(datetime.datetime.today)f
下面使用 print_time
裝飾函數foo
:
@print_timedef foo:time.sleep(2)print('hello world')
當調用 foo
函數時,抛出如下異常:
foo---------------------------------------------------------------------------TypeError Traceback (most recent call last)<ipython-input-27-c19b6d9633cf> in <module>----> 1 fooTypeError: 'NoneType' object is not callable
所以,按照如上定義 print_time
裝飾器,肯定是不行的。
要想明白為啥不行,首先要知道裝飾器這個語法的本質。其實很簡單,@print_time
裝飾foo
函數等于:
foo = print_time(foo)
就是這一行代碼,再也沒有其他。
因為上面的 print_time
無返回值,所以賦值給foo
函數後,foo
函數變為 None,所以當調用foo
時抛出'NoneType' object is not callable
這也就不足為奇了。
3 應該怎麼寫
print_time
需要返回一個函數,這樣賦值給foo
函數後,正确寫法如下所示:
import datetimeimport timedef print_time(g):def f:print('開始執行時間')print(datetime.datetime.today)gprint('結束時間')print(datetime.datetime.today)return f
裝飾 foo
:
@print_timedef foo:time.sleep(2)print('hello world')
調用 foo
,運行結果如下:
foo開始執行時間2021-04-02 22:32:49.114124hello world結束時間2021-04-02 22:32:51.119506
一切正常
4 裝飾器好處
上面自定義print_time
裝飾器,除了能裝飾foo
函數外,還能裝飾任意其他函數和類内方法。
裝飾任意一個函數 foo2
:
@print_timedef foo2:print('this is foo2')
裝飾類内方法 foo3
,需要稍微修改原來的print_time
:
def print_time(g):def f(*args, **kargs):print('開始執行時間')print(datetime.datetime.today)g(*args, **kargs)print('結束時間')print(datetime.datetime.today)return f
為類MyClass
中foo3
方法增加print_time
裝飾:
class MyClass(object):@print_timedef foo3(self):print('this is a method of class')
執行結果如下:
MyClass.foo3開始執行時間2021-04-02 23:16:32.094025this is a method of class結束時間2021-04-02 23:16:32.094078
以上就是裝飾器的通俗解釋,平時可以多用用,讓我們的代碼更加精煉、可讀。
這是我的第454篇原創,若有幫助,歡迎點贊、分享。
今天給大家推薦一本機器學習、深度學習的人都應該聽說過一本經典教材: 《Pattern Recognition and Machine Learning》,中文譯名《模式識别與機器學習》,簡稱 PRML。 出自微軟劍橋研究院實驗室主任 Christopher Bishop 大神之手。 對,就是豆瓣評分 9.5 的這本書。
資料獲取方法
2. 後台回複關鍵詞: PRML
回複「PRML」即可獲取資料
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!