Python中如何淺談裝飾器

本篇文章給大家分享的是有關(guān)Python中如何淺談裝飾器,小編覺得挺實用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

創(chuàng)新互聯(lián)專注于葫蘆島企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站開發(fā),商城系統(tǒng)網(wǎng)站開發(fā)。葫蘆島網(wǎng)站建設(shè)公司,為葫蘆島等地區(qū)提供建站服務(wù)。全流程定制網(wǎng)站開發(fā),專業(yè)設(shè)計,全程項目跟蹤,創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)

一 裝飾器是什么
   裝飾器是一個用于封裝函數(shù)或者類的代碼工具,顯式地將封裝器作用于函數(shù)或者類上,達到程序運行時動態(tài)增加功能的目的。對于函數(shù)運行前處理常見前置條件(常見的web登陸授權(quán)驗證),或者在函數(shù)執(zhí)行之后做善后工作(比如異常處理,記錄log 等等)。

二 如何使用裝飾器
   裝飾器本質(zhì)上就是一個可用接受調(diào)用也可以返回調(diào)用的高階函數(shù)。該函數(shù)以被裝飾的函數(shù)為參數(shù)(還可以加上其他值作為參數(shù))。在裝飾器內(nèi)進行裝飾器的邏輯處理,執(zhí)行被裝飾函數(shù),并返回一個裝飾過的函數(shù),聽起來是不是有點繞,Talk is cheap,show me the code . 
下面使用函數(shù)now 和函數(shù)add作為例子,

  1. import datetime

  2. def now():

  3.     print 'now is ', datetime.datetime.today()

  4. def add(x, y):

  5.     ret = x + y

  6.     print '{x} + {y} = {retval}'.format(x=x,y=y,retval=ret)

2.1 裝飾器語法
   有兩種方式顯示調(diào)用裝飾器的方法。
   方法一:func = deco(func)
   方法二:Python 2.5之后 為裝飾器引入了特殊的語法 @ --語法糖,在裝飾器名稱前使用@ 符號,添加在被裝飾的函數(shù)定義之前。 

  1. @deco

  2.    def now():

  3.        print 'now is ', datetime.datetime.today()

  4.    # 調(diào)用now

  5.    now()

小編將從 參數(shù)這個角度來由淺入深介紹裝飾器,函數(shù)有不帶參數(shù)和帶參數(shù)的兩種情況,裝飾器也有帶參數(shù)和不帶參數(shù)的兩種情況,裝飾器對處理帶參數(shù)和不帶參數(shù)的情況也會有鎖不同。
2.2 不帶參數(shù)的情況
  我們需要在調(diào)用函數(shù) now 之前和之后加上調(diào)用記錄。

  1. def deco(func):

  2.     print 'begin call %s():' % (func.__name__)

  3.     func()

  4.     print 'end call %s():' % (func.__name__)

  5.     return  func #裝飾器的參數(shù)是被裝飾的函數(shù)對象,返回原函數(shù)的對象。

  1. yangyiDBA:test yangyi$ python 1.py

  2. begin call now():

  3. now is  2017-05-01 14:40:57.309836

  4. end call now():

  5. now is  2017-05-01 14:40:57.309868

但是從上面的例子看 結(jié)果輸出了兩次now 時間,明顯不符合我們的要求,因為裝飾器必須返回被調(diào)用函數(shù),return func的時候發(fā)生了第二次。后面我們會解決這個問題。
2.3 帶參數(shù)的情況,因為函數(shù)的參數(shù)個數(shù)是不確定的 ,我們需要借助(*args, **kwargs),自動適應(yīng)變參和命名參數(shù)。

  1. #!/usr/bin/env  python

  2. # coding:utf-8

  3. import datetime

  4. import functools

  5. def deco(func):

  6.     @functools.wraps(func) #

  7.     def wrapper(*args, **kw):

  8.         print 'begin call %s():' % (func.__name__)

  9.         result=func(*args, **kw) #  如果函數(shù)無返回值 ,可以直接使用func(*args, **kw)

  10.         print 'end call %s():' % (func.__name__)

  11.         return result #這里 result 是為了func 有返回值,

  12.     return wrapper

  13. @deco

  14. def add(x, y):

  15.     ret = x + y

  16.     print '{x} + {y} = {retval}'.format(x=x,y=y,retval=ret)

  17. @deco

  18. def now():

  19.     print 'now is ', datetime.datetime.today()

  20. add(2,5)

  21. now()

上面的裝飾器做了如下事情
1 函數(shù)func作為參數(shù)傳給 deco()。
2 functool.wraps 將func 的屬性復(fù)制給 warper。
3 執(zhí)行函數(shù)func前后執(zhí)行某些動作。
4 返回結(jié)果。
5 返回wrapper 函數(shù)對象。
這里特別說明functool.wraps的作用,由于裝飾器導(dǎo)致解釋器認為函數(shù)本身發(fā)生了改變,在某些情況下可能會導(dǎo)致一些問題。Python通過functool.wraps解決了這個問題:
在編寫裝飾器時,在實現(xiàn)前加入 @functools.wraps(func) 可以保證裝飾器不會對被裝飾函數(shù)造成影響。
特別說明其他要使用裝飾器的時候會有其他的寫法 比如直接返回被裝飾的函數(shù)。

  1. def deco(func):

  2.     @functools.wraps(func) #

  3.     def wrapper(*args, **kw):

  4.         print 'begin call %s():' % (func.__name__)

  5.         return func(*args, **kw)

  6.     return wrapper

輸出

  1. yangyiDBA:test yangyi$ python 1.py

  2. begin call add():

  3. 2 + 5 = 7

  4. end call add():

  5. begin call now():

  6. now is  2017-05-01 15:20:51.597859

  7. end call now():

2.4 帶參數(shù)的裝飾器
如果裝飾器本身傳入?yún)?shù),就需要編寫一個返回decorator的高階函數(shù),寫出來會更復(fù)雜。比如,要自定義log的文本:

  1. #!/usr/bin/env  python

  2. # coding:utf-8

  3. import datetime

  4. import functools

  5. def deco(text):

  6.     def _deco(func):

  7.         def wrapper(*args, **kw):

  8.             print '%s, begin call %s():' % (text,func.__name__)

  9.             result=func(*args, **kw) #  如果函數(shù)無返回值 ,可以直接使用func(*args, **kw)

  10.             print '%s, end call %s():' % (text,func.__name__)

  11.             return result #這里 result 是為了func 有返回值,

  12.         return wrapper

  13.     return _deco

  14. @deco("yangyi")

  15. def add(x, y):

  16.     ret = x + y

  17.     print '{x} + {y} = {retval}'.format(x=x,y=y,retval=ret)

  18. @deco("youzan")

  19. def now():

  20.     print 'now is ', datetime.datetime.today()

  21. add(2,5)

  22. now()

測試結(jié)果:

  1. yangyiDBA:test yangyi$ python 2.py

  2. yangyi, begin call add():

  3. 2 + 5 = 7

  4. yangyi, end call add():

  5. youzan, begin call now():

  6. now is  2017-05-01 18:47:54.728296

  7. youzan, end call now():

2.5 Python內(nèi)置裝飾器
在Python中有三個內(nèi)置的裝飾器,都是跟class相關(guān)的:staticmethod、classmethod 和property。
staticmethod 是類靜態(tài)方法,其跟成員方法的區(qū)別是沒有 self 參數(shù),并且可以在類不進行實例化的情況下調(diào)用
classmethod  與成員方法的區(qū)別在于所接收的第一個參數(shù)不是 self (類實例的指針),而是cls(當(dāng)前類的具體類型)
property 是屬性的意思,表示可以通過通過類實例直接訪問的信息

2.6 跨文件調(diào)用,因為裝飾器本質(zhì)是一個函數(shù)。在工程實現(xiàn)里我們可以通過創(chuàng)建一個公用的decorator,作為基礎(chǔ)裝飾器供其他函數(shù)調(diào)用。
   Python一切皆對象,函數(shù)也是,也可以賦值給其他變量,理解這點再去理解裝飾器就容易多了。

以上就是Python中如何淺談裝飾器,小編相信有部分知識點可能是我們?nèi)粘9ぷ鲿姷交蛴玫降摹OM隳芡ㄟ^這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

分享標(biāo)題:Python中如何淺談裝飾器
本文路徑:http://bm7419.com/article20/jdihjo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供手機網(wǎng)站建設(shè)、網(wǎng)站制作、動態(tài)網(wǎng)站、軟件開發(fā)響應(yīng)式網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站制作