前言
本文的文字及圖片來源于網路,僅供學習、交流使用,不具有任何商業用途,如有問題請及時聯系我們以作處理,
PS:如有需要Python學習資料的小伙伴可以點擊下方鏈接自行獲取
Python免費學習資料、代碼以及交流解答點擊即可加入
python裝飾器本質上就是一個函式,它可以讓其他函式在不需要做任何代碼變動的前提下增加額外的功能,裝飾器的回傳值也是一個函式物件,
很多python初學者學到面向物件類和方法是一道大坎,那么python中的裝飾器是你進入Python高級語法大門的一道坎,
計算函式運行時間
假設你寫了幾個函式,有一天領導心血來潮說,你把每個函式的運行時長(結束時間-開始時間)統計下,作為一個python實習生的你可能會這樣寫
原始函式

?
添加運行時長
作為一個實習生的你,可能想到的解決辦法如下

?
運行結果:

?
上面的代碼雖然滿足了領導的要求,但是如果你寫的函式很多的話,每個函式都這樣去添加,會顯得代碼很臃腫,有很多重復代碼,
有一天你邊上的一個python老司機看了下你的代碼,給你指了條明路:裝飾器
函式裝飾器
裝飾器可以寫成函式式裝飾器,也可以寫成一個類裝飾器,先從簡單的函式裝飾器開始學習,
python裝飾器本質上就是一個函式,它可以讓其他函式在不需要做任何代碼變動的前提下增加額外的功能,裝飾器的回傳值也是一個函式物件,
runtime函式就是一個裝飾器了,它對原函式做了包裝并回傳了另外一個函式,額外添加了一些功能,在函式上方使用@語法糖就可以呼叫這個裝飾器了

?
運行結果

?
函式帶引數裝飾器
上面的runtime就是一個簡單的裝飾器模型了,但并不強壯,如果函式里面帶有引數,那就不管用了,并且函式的引數是不固定的,這時候就需要用到args,*kwargs兩兄弟了

?
類裝飾器
關于call方法,不得不先提到一個概念,就是可呼叫物件(callable),我們平時自定義的函式、內置函式和類都屬于可呼叫物件,
但凡是可以把一對括號()應用到某個物件身上都可稱之為可呼叫物件,判斷物件是否為可呼叫物件可以用函式 callable,
如果在類中實作了call方法,那么實體物件也將成為一個可呼叫物件

?
裝飾器帶引數
快到年底了,領導說運行的速度先不要太快了,讓客戶先加錢,然后再以正常的速度顯示,那么現在的需求是讓每個函式的運行時間加50%,該如何實作呢?
這就到了裝飾器的高級語法,裝飾器也需要帶上引數了
函式裝飾器

?
類裝飾器

?
使用場景
用哪些地方需要使用裝飾器呢?
- 如果你用過locust,設定權重會用到@task(1),
- 如果你用過pytest框架,使用fixture功能的時候經常會用到@pytest.fixture(scope="function")
- allure里面可以添加測驗步驟 @allure.step('修改購物車')
- 被大量使用于Flask和Django web框架中,檢查是否被授權去使用一個web應用的端點(endpoint),如 @login_required
- 也可以自己寫個裝飾器添加日志
前面一篇對python裝飾器有了初步的了解了,但是還不夠完美,領導看了后又提出了新的需求,希望運行的日志能顯示出具體運行的哪個函式,
name和doc
__ name __用于獲取函式的名稱, __ doc __用于獲取函式的docstring內容(函式的注釋)

?
裝飾器加函式名稱日志
在裝飾器里面添加2行代碼,列印正在運行函式的名稱和docstring內容

?
運行結果

?
從運行的結果可以看出,func_a.__ name __ 運行的結果是wrapper,func_a. __ doc__運行的結果是wrapper inner fuction,
也就是說被裝飾后的函式其實已經是另外一個函式了(函式名等函式屬性會發生改變),那這個問題如何解決呢?
這就需要用到functools里面的一個wraps函式了
functools
當func_a函式被裝飾后,導致了一個副作用:自身的函式屬性和docstring內容變成了wrapper函式的屬性了,
這里需用到functools里面的一個wraps的裝飾器來消除這樣的副作用,

?
只需在wrapper函式上加上@wraps(func)即可解決
運行結果

?
類裝飾器
帶引數的裝飾器,可以寫成類裝飾器

?
運行結果

?
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/266596.html
標籤:Python
