日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
這樣用裝飾器,為什么不行?

最近幾周,陸續(xù)收到幾位讀者關(guān)于裝飾器使用的提問(wèn),今天統(tǒng)一回復(fù)。

1. 問(wèn)題

大概問(wèn)題是這樣,想要自定義一個(gè)Python裝飾器,問(wèn)我這樣寫裝飾器行不行?如果不行,那又是為什么?

 
 
 
  1. import datetime 
  2. import time 
  3.  
  4. def print_time(g): 
  5.     def f(): 
  6.         print('開始執(zhí)行時(shí)間') 
  7.         print(datetime.datetime.today()) 
  8.          
  9.         g() 
  10.          
  11.         print('結(jié)束時(shí)間') 
  12.         print(datetime.datetime.today()) 
  13.     f() 

下面使用 print_time裝飾函數(shù) foo:

 
 
 
  1. @print_time 
  2. def foo(): 
  3.     time.sleep(2) 
  4.     print('hello world') 

當(dāng)調(diào)用 foo函數(shù)時(shí),拋出如下異常:

 
 
 
  1. foo() 
  2.  
  3. --------------------------------------------------------------------------- 
  4. TypeError                                 Traceback (most recent call last) 
  5.  in  
  6. ----> 1 foo() 
  7.  
  8. TypeError: 'NoneType' object is not callable 

所以,按照如上定義 print_time裝飾器,肯定是不行的。

2. 為什么不行

要想明白為啥不行,首先要知道裝飾器這個(gè)語(yǔ)法的本質(zhì)。其實(shí)很簡(jiǎn)單,@print_time裝飾foo函數(shù)等于:

 
 
 
  1. foo = print_time(foo) 

就是這一行代碼,再也沒(méi)有其他。

因?yàn)樯厦娴?print_time 無(wú)返回值,所以賦值給 foo 函數(shù)后,foo 函數(shù)變?yōu)?None,所以當(dāng)調(diào)用 foo() 時(shí)拋出 'NoneType' object is not callable

這也就不足為奇了。

3. 應(yīng)該怎么寫

print_time 需要返回一個(gè)函數(shù),這樣賦值給 foo函數(shù)后,正確寫法如下所示:

 
 
 
  1. import datetime 
  2. import time 
  3.  
  4. def print_time(g): 
  5.     def f(): 
  6.         print('開始執(zhí)行時(shí)間') 
  7.         print(datetime.datetime.today()) 
  8.          
  9.         g() 
  10.          
  11.         print('結(jié)束時(shí)間') 
  12.         print(datetime.datetime.today()) 
  13.     return f 

裝飾 foo:

 
 
 
  1. @print_time 
  2. def foo(): 
  3.     time.sleep(2) 
  4.     print('hello world') 

調(diào)用 foo ,運(yùn)行結(jié)果如下:

 
 
 
  1. foo() 
  2.  
  3. 開始執(zhí)行時(shí)間 
  4. 2021-04-02 22:32:49.114124 
  5. hello world 
  6. 結(jié)束時(shí)間 
  7. 2021-04-02 22:32:51.119506 

一切正常

4. 裝飾器好處

上面自定義print_time裝飾器,除了能裝飾foo函數(shù)外,還能裝飾任意其他函數(shù)和類內(nèi)方法。

裝飾任意一個(gè)函數(shù) foo2:

 
 
 
  1. @print_time 
  2. def foo2(): 
  3.   print('this is foo2') 

裝飾類內(nèi)方法 foo3,需要稍微修改原來(lái)的print_time:

 
 
 
  1. def print_time(g): 
  2.     def f(*args, **kargs): 
  3.         print('開始執(zhí)行時(shí)間') 
  4.         print(datetime.datetime.today()) 
  5.      
  6.         g(*args, **kargs) 
  7.      
  8.         print('結(jié)束時(shí)間') 
  9.         print(datetime.datetime.today()) 
  10.     return f 

為類MyClass中foo3方法增加print_time裝飾:

 
 
 
  1. class MyClass(object): 
  2.     @print_time 
  3.     def foo3(self): 
  4.         print('this is a method of class') 

執(zhí)行結(jié)果如下:

 
 
 
  1. MyClass().foo3() 
  2.  
  3. 開始執(zhí)行時(shí)間 
  4. 2021-04-02 23:16:32.094025 
  5. this is a method of class 
  6. 結(jié)束時(shí)間 
  7. 2021-04-02 23:16:32.094078 

以上就是裝飾器的通俗解釋,平時(shí)可以多用用,讓我們的代碼更加精煉、可讀。


分享標(biāo)題:這樣用裝飾器,為什么不行?
網(wǎng)站地址:http://www.dlmjj.cn/article/djegsod.html