最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python裝飾器使用你可能不知道的幾種姿勢

 更新時間:2019年10月25日 08:20:59   作者:麥麥麥造  
這篇文章主要給大家介紹了關(guān)于Python裝飾器使用你可能不知道的幾種姿勢,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者使用Python具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧

前言

在Python中,裝飾器是一種十分強大并且好用的語法,一些重復(fù)的代碼使用裝飾器語法的話能夠使代碼更容易理解及閱讀。

因此在這里簡單總結(jié)了一下Python中裝飾器的幾種用法以及需要注意的事情。

一、在裝飾器中獲取被裝飾函數(shù)的參數(shù)

假設(shè)我們在開發(fā)web的時候,需要做反爬。要判斷接口的訪問來源我們就可以通過下面裝飾器的方法來實現(xiàn):

def mydecorator(func):
 def wrapped(*args, **kwargs):
  print("進入裝飾器")
  if args[0]['header'] == 'spider':
   print("code: 400")
   return

  result = func(*args, **kwargs)
  return result

 return wrapped
@mydecorator
def request_page(request):
 print("一個訪問請求")
 print("返回了response")
if __name__ == '__main__':
 request = {
  'data': 100,
  'header': 'spider'
 }
 request_page(request)

在這個裝飾器中,我們在裝飾器中獲取了request中的header參數(shù),如果判斷訪問來源于爬蟲,那么便給它返回一個400。
使用裝飾器的寫法等同于下面不使用裝飾器的寫法

def mydecorator(*args, **kwargs):
 print("進入函數(shù)")
 if args[0]['header'] == 'spider':
  print("code: 400")
  return False
 return True
def request_page(request):
 if not mydecorator(request):
  return
 print("訪問一個網(wǎng)頁")
 print("得到了response")
if __name__ == '__main__':
 request = {
  'data': 100,
  'header': 'spider'
 }
 request_page(request)

在只需要裝飾一個函數(shù)的時候后面一種寫法可能更優(yōu)于裝飾器的寫法,但是在需要裝飾很多個函數(shù)的時候,使用裝飾器明顯是更好的選擇。

二、在裝飾器獲取函數(shù)的返回值

有的時候我們需要對函數(shù)的返回值做出判斷,但又不想直接將判斷寫在函數(shù)里的時候,我們也可以使用裝飾器來實現(xiàn):

def mydecorator(func):
 def wrapped(*args, **kwargs):
  print("進入裝飾器")
  result = func(*args, **kwargs)
  if result == 400:
   print("response is 400!")
   return False
  return True
 return wrapped

@mydecorator
def request_page():
 print("訪問一個網(wǎng)頁")
 print("得到了response")
 return 200

if __name__ == '__main__':
 print(request_page())

三、給裝飾器傳入?yún)?shù)

在實際應(yīng)用中,我們有時需要根據(jù)函數(shù)的執(zhí)行狀態(tài)來重復(fù)執(zhí)行。例如在編寫爬蟲的時候,可能由于網(wǎng)絡(luò)的原因會導(dǎo)致一些頁面訪問失敗,這時我們就需要根據(jù)爬蟲的返回結(jié)果進行重復(fù)請求。

def retry(MAXRETRY=3):
 def decorator(func):
  def wrapped(*args, **kwargs):
   print("進入裝飾器")

   result = 0
   retry = 1
   while result != 200 and retry <= MAXRETRY:
    result = func(*args, **kwargs)
    print("重試第%s次" % retry)
    retry += 1

   return result

  return wrapped

 return decorator
 
@retry(5)
def request_page():
 print("訪問一個網(wǎng)頁")
 print("得到了response")
 return 400

在這里我們假設(shè)訪問一個網(wǎng)頁得到400的時候便重新請求。我們在retry裝飾器里傳了一個5,這表示我們希望重試的最大次數(shù)為5次,如果不傳入這個值,那么它的默認重試次數(shù)則為3次。

在熟悉了基本裝飾器的寫法后,傳參裝飾器的寫法也十分的好理解了。就是在外面多加了一層函數(shù),用于傳入?yún)?shù)。

四、裝飾器文檔的問題

我們都知道通過魔術(shù)方法__doc__可以獲取我們寫在代碼中的文檔,那么你是否知道使用裝飾器后,會造成被包裝函數(shù)的文檔被裝飾器的文檔覆蓋的問題呢。

def request_page():
 '''
 request_page 函數(shù)文檔
 :return:
 '''
 print("訪問一個網(wǎng)頁")
 print("得到了response")

if __name__ == '__main__':
 print(request_page.__doc__)

在上面對上面未使用裝飾的代碼使用__doc__方法的時候,我們得到的結(jié)果是:

In[3]: request_page.__doc__
Out[3]: '\n  request_page 函數(shù)文檔\n  :return:\n  '

這是我們理想中的結(jié)果!

但是當(dāng)我們將上述函數(shù)使用裝飾器裝飾后:

def decorator(func):
  def wrapped(*args, **kwargs):
    '''
    裝飾器文檔
    :param args:
    :param kwargs:
    :return:
    '''
    print("進入裝飾器")
    result = func(*args, **kwargs)
    return result

  return wrapped


@decorator
def request_page():
  '''
  request_page 函數(shù)文檔
  :return:
  '''
  print("訪問一個網(wǎng)頁")
  print("得到了response")
  

我們再一次運行__doc__魔術(shù)方法的時候,得到的結(jié)果卻是裝飾器的內(nèi)部文檔:

In[4]: request_page.__doc__
Out[4]: '\n    裝飾器文檔\n    :param args:\n    :param kwargs:\n    :return:\n    '
In[5]: request_page.__name__
Out[5]: 'wrapped'

這個問題會使得我們的調(diào)試變得困難,也會使許多自動文檔生成工具失去效果。

解決這個問題的最好辦法就是使用 functools包的wraps()模塊來將裝飾器進行一個包裝。

from functools import wraps
def decorator(func):

  @wraps(func)
  def wrapped(*args, **kwargs):
    '''
    裝飾器
    :param args:
    :param kwargs:
    :return:
    '''
    print("進入裝飾器")
    result = func(*args, **kwargs)
    return result
  return wrapped

@decorator
def request_page():
  '''
  request_page 函數(shù)文檔
  :return:
  '''
  print("訪問一個網(wǎng)頁")
  print("得到了response")
  

使用wraps將裝飾器裝飾后,這樣我們的函數(shù)便能夠保存它的一些重要數(shù)據(jù)了。

In[3]: request_page.__doc__
Out[3]: '\n  request_page 函數(shù)文檔\n  :return:\n  '
In[3]: request_page.__name__
Out[4]: 'request_page'

五、使用class的寫法來編寫裝飾器

雖然大多數(shù)的裝飾器都是通過函數(shù)的寫法來實現(xiàn)的,但同樣的可以通過類的寫法來實現(xiàn)裝飾器。

使用類的寫法,我們可以實現(xiàn)一些使用函數(shù)寫法不太好實現(xiàn)的需求。例如記錄一個函數(shù)執(zhí)行的次數(shù)

class Decorator():
  def __init__(self,func):
    print('類初始化')
    self.func = func
    self.count = 0
  def __call__(self, *args, **kwargs):
    print('進入裝飾器')
    result = self.func(*args,**kwargs)
    self.count += 1

    return result
@Decorator
def request_page():
  '''
  request_page
  :return:
  '''
  print("訪問一個網(wǎng)頁")
  print("得到了response")

六、總結(jié)

裝飾器是Python里比較高級的一種語法,這里只是介紹了它的幾種使用技巧,以及需要注意的問題。借用金庸先生的話,“武功無高低,修為有深淺”。想要更加靈活的使用裝飾器,深入理解它的原理,我們在平時還是需要加強基本功的學(xué)習(xí)!

好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對腳本之家的支持。

相關(guān)文章

  • python使用技巧-查找文件?

    python使用技巧-查找文件?

    這篇文章主要分享的是python使用技巧查找文件,下面我們就來介紹針對python查找文件的相關(guān)內(nèi)容,需要的小伙伴可以參考一下
    2022-02-02
  • 解決Python中導(dǎo)入自己寫的類,被劃紅線,但不影響執(zhí)行的問題

    解決Python中導(dǎo)入自己寫的類,被劃紅線,但不影響執(zhí)行的問題

    這篇文章主要介紹了解決Python中導(dǎo)入自己寫的類,被劃紅線,但不影響執(zhí)行的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-07-07
  • 使用Python實現(xiàn)首頁通知功能

    使用Python實現(xiàn)首頁通知功能

    這篇文章主要為大家詳細介紹了如何使用Python實現(xiàn)首頁通知功能,文中的示例代碼講解詳細,具有一定的借鑒價值,有需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-02-02
  • Python中使用語句導(dǎo)入模塊或包的機制研究

    Python中使用語句導(dǎo)入模塊或包的機制研究

    這篇文章主要介紹了Python中使用語句導(dǎo)入模塊或包的機制研究,同時對比了幾種導(dǎo)入包或模塊的語句并簡要說明了這幾種方法之間的幾點優(yōu)劣,需要的朋友可以參考下
    2015-03-03
  • Python中CSV文件的讀寫庫操作方法

    Python中CSV文件的讀寫庫操作方法

    Python 中提供了一個官方的標(biāo)準(zhǔn)庫來處理這種文件類型,那就是 CSV 庫,這篇文章主要介紹了Python中CSV文件的讀寫庫,需要的朋友可以參考下
    2022-12-12
  • Python&Matlab實現(xiàn)櫻花的繪制

    Python&Matlab實現(xiàn)櫻花的繪制

    正值櫻花飄落的季節(jié),本文將利用Python和Matlab分別繪制一顆櫻花樹,文中的示例代碼講解詳細,感興趣的小伙伴快跟隨小編一起動手嘗試一下
    2022-04-04
  • 使用Python對Dicom文件進行讀取與寫入的實現(xiàn)

    使用Python對Dicom文件進行讀取與寫入的實現(xiàn)

    這篇文章主要介紹了使用Python對Dicom文件進行讀取與寫入的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04
  • Python 常用 PEP8 編碼規(guī)范詳解

    Python 常用 PEP8 編碼規(guī)范詳解

    這篇文章主要介紹了Python 常用 PEP8 編碼規(guī)范詳解的相關(guān)資料,需要的朋友可以參考下
    2017-01-01
  • python列表反轉(zhuǎn)的4種方法

    python列表反轉(zhuǎn)的4種方法

    本文主要介紹了python列表反轉(zhuǎn)的4種方法,包括reverse()方法、reversed()函數(shù)、切片語法和for循環(huán),具有一定的參考價值,感興趣的可以了解一下
    2025-03-03
  • python接口自動化測試數(shù)據(jù)和代碼分離解析

    python接口自動化測試數(shù)據(jù)和代碼分離解析

    代碼的可維護性除了代碼冗余之外還有就是數(shù)據(jù)盡量不要和代碼摻雜在一起,因為閱讀起來會非常的凌亂;數(shù)據(jù)分離能更好的增加代碼可讀性和可維護性,也能更好的二次修改使用
    2021-09-09

最新評論

西安市| 区。| 紫阳县| 雅江县| 沿河| 兰考县| 邢台市| 襄樊市| 舟曲县| 襄垣县| 东台市| 禄丰县| 佳木斯市| 遂宁市| 绍兴县| 右玉县| 津市市| 聂拉木县| 金山区| 綦江县| 新闻| 板桥市| 吴桥县| 瑞昌市| 宝山区| 外汇| 淮阳县| 大余县| 山西省| 河曲县| 施甸县| 黄冈市| 阿拉善右旗| 新竹市| 梁河县| 舟山市| 房产| 阳江市| 肃宁县| 承德市| 井研县|