日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

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

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
搞定三大神器之Python裝飾器

裝飾器,幾乎各大Python框架中都能看到它的身影,足以表明它的價(jià)值!它有動(dòng)態(tài)改變函數(shù)或類(lèi)功能的魔力!

成都創(chuàng)新互聯(lián)是網(wǎng)站建設(shè)專(zhuān)家,致力于互聯(lián)網(wǎng)品牌建設(shè)與網(wǎng)絡(luò)營(yíng)銷(xiāo),專(zhuān)業(yè)領(lǐng)域包括成都網(wǎng)站制作、做網(wǎng)站、外貿(mào)營(yíng)銷(xiāo)網(wǎng)站建設(shè)、電商網(wǎng)站制作開(kāi)發(fā)、小程序開(kāi)發(fā)、微信營(yíng)銷(xiāo)、系統(tǒng)平臺(tái)開(kāi)發(fā),與其他網(wǎng)站設(shè)計(jì)及系統(tǒng)開(kāi)發(fā)公司不同,我們的整合解決方案結(jié)合了恒基網(wǎng)絡(luò)品牌建設(shè)經(jīng)驗(yàn)和互聯(lián)網(wǎng)整合營(yíng)銷(xiāo)的理念,并將策略和執(zhí)行緊密結(jié)合,且不斷評(píng)估并優(yōu)化我們的方案,為客戶提供全方位的互聯(lián)網(wǎng)品牌整合方案!

1. 什么是裝飾器

對(duì)于受到封裝的原函數(shù)比如f來(lái)說(shuō),裝飾器能夠在f函數(shù)執(zhí)行前或者執(zhí)行后分別運(yùn)行一些代碼。

2. 裝飾器的結(jié)構(gòu)

裝飾器也是一個(gè)函數(shù),它裝飾原函數(shù)f或類(lèi)cls后,再返回一個(gè)函數(shù)g

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

 
 
 
  1. def decorator(f): 
  2.   # 定義要返回的函數(shù) 
  3.   def g(): 
  4.     print('函數(shù)f執(zhí)行前的動(dòng)作') 
  5.     f() 
  6.     print('函數(shù)f執(zhí)行后的動(dòng)作') 
  7.   return g 

裝飾一個(gè)類(lèi):

 
 
 
  1. def decorator(cls): 
  2.   # 定義要返回的函數(shù) 
  3.   def g(): 
  4.     print('類(lèi)cls執(zhí)行前的動(dòng)作') 
  5.     f() 
  6.     print('類(lèi)cls執(zhí)行后的動(dòng)作') 
  7.   return g 

使用裝飾器很簡(jiǎn)單,@+自定義裝飾器 裝飾要想裝飾的函數(shù)。

3. 為什么要這樣

要想理解裝飾器為什么要有這種結(jié)構(gòu),要首先想明白裝飾器的目標(biāo)是什么。

它的價(jià)值在于為原函數(shù)f增加一些行為,前提必須不能破壞函數(shù)f,所以肯定不能改變f的內(nèi)部結(jié)構(gòu),所以只能在調(diào)用f前后定義一些行為。

同時(shí),裝飾器函數(shù)decorator返回值又是什么?你可以思考下,返回一個(gè)函數(shù)是再好不過(guò)的了,它包裝了原函數(shù)f.

4. 裝飾一個(gè)函數(shù)

printStar函數(shù)接收一個(gè)函數(shù)f,返回值也是一個(gè)函數(shù),所以滿足裝飾器的結(jié)構(gòu)要求,所以printStar是一個(gè)裝飾器。

 
 
 
  1. def printStar(f): 
  2.     def g(): 
  3.         print('*'*20) 
  4.         f() 
  5.         print('*'*20) 
  6.     return g 

printStar裝飾器實(shí)現(xiàn)f函數(shù)執(zhí)行前、后各打印20個(gè)*字符。

使用printStar:

 
 
 
  1. @printStar 
  2. def f(): 
  3.     print('hello world') 

調(diào)用:

 
 
 
  1. if __name__ == '__main__': 
  2.    ### 改變函數(shù)功能 
  3.    f() 

打印結(jié)果:

 
 
 
  1. ******************** 
  2. hello world 
  3. ******************** 

可以很方便的裝飾要想裝飾的其他函數(shù),如下:

 
 
 
  1. @printStar 
  2. def g(): 
  3.     print('welcome to Python') 

5. 裝飾一個(gè)類(lèi)

除了可以裝飾函數(shù)f外,還可以裝飾類(lèi)cls,兩者原理都是一樣的。

下面給出一個(gè)裝飾器實(shí)現(xiàn)單例模式的例子,所謂單例就是類(lèi)只有唯一實(shí)例,不能有第二個(gè)。

 
 
 
  1. def singleton(cls): 
  2.    instance = {} 
  3.  
  4.    def get_instance(*args, **kwargs): 
  5.        if cls not in instance: 
  6.            instance[cls] = cls(*args, **kwargs) 
  7.        return instance[cls] 
  8.    return get_instance 

定義字典instance,鍵值對(duì)分別為類(lèi)和實(shí)例,這樣確保只cls()一次。

使用裝飾器singleton修飾類(lèi):

 
 
 
  1. @singleton 
  2. class CorePoint: 
  3.    pass 

測(cè)試:

 
 
 
  1. if __name__ == '__main__': 
  2.    ### 改變類(lèi)的功能 
  3.    c1 = CorePoint() 
  4.    c2 = CorePoint() 
  5.    print(c1 is c2) # True 

6. 裝飾器層疊

上面原函數(shù)f不僅能被一個(gè)裝飾器修飾,還能被n多個(gè)裝飾器修飾。

下面再定義一個(gè)裝飾器printLine,被修飾函數(shù)執(zhí)行前后打印20個(gè):

 
 
 
  1. def printLine(f): 
  2.     def g(): 
  3.         print('-'*20) 
  4.         f() 
  5.         print('-'*20) 
  6.     return g 

使用上文定義好的printStar和printLine同時(shí)裝飾函數(shù)f:

 
 
 
  1. @printStar 
  2. @printLine 
  3. def f(): 
  4.     print('hello world') 

此時(shí)再調(diào)用函數(shù)f:

 
 
 
  1. if __name__ == '__main__': 
  2.    ### 改變函數(shù)功能 
  3.    f() 

打印結(jié)果:

 
 
 
  1. ******************** 
  2. -------------------- 
  3. hello world 
  4. -------------------- 
  5. ******************** 

f被裝飾后,先打印*,再打印 -

層疊多一層,原函數(shù)f就變強(qiáng)大一層。使用裝飾器,還能實(shí)現(xiàn)功能抽離,進(jìn)一步實(shí)現(xiàn)松耦合。

7. 溫馨提醒

打印原函數(shù)f的名字__name__,結(jié)果為f

 
 
 
  1. In [1]: def f():  
  2.    ...:     pass  
  3.  
  4. In [4]: f.__name__                                                               
  5. Out[4]: 'f' 

但是,被裝飾后函數(shù)名字f變?yōu)間,這不是我們希望的!

 
 
 
  1. @printStar 
  2. def f(): 
  3.   pass 
  4.  
  5. f() 
  6. f.__name__ # g 

Python提供的解決方案:使用functools模塊中的wraps裝飾器:

 
 
 
  1. from functools import wraps 
  2.  
  3. def printStar(f): 
  4.     @wraps(f) 
  5.     def g(): 
  6.         print('*'*20) 
  7.         f() 
  8.         print('*'*20) 
  9.     return g 

此時(shí)再打印被裝飾后f的名字,顯示f,正常!


本文標(biāo)題:搞定三大神器之Python裝飾器
網(wǎng)頁(yè)路徑:http://www.5511xx.com/article/copihcp.html