Python函式裝飾器2

2021-08-28 09:27:59 字數 2697 閱讀 1972

先看這篇,簡單複習一下裝飾器大致的功能:

這篇寫的比較全,但是有點晦澀難懂:

推薦這篇,是原作者自己分析的,但是感覺有點雜亂:

*************************==核心部分***********************************==

裝飾器(decorators)是 python 的乙個重要部分。簡單地說:他們是修改其他函式的功能的函式。他們有助於讓我們的**更簡短,也更pythonic(python範兒)。大多數初學者不知道在哪兒使用它們,所以我將要分享下,哪些區域裡裝飾器可以讓你的**更簡潔。 首先,讓我們討論下如何寫你自己的裝飾器。

這可能是最難掌握的概念之一。我們會每次只討論乙個步驟,這樣你能完全理解它。

首先我們來理解下 python 中的函式:

剛才那些就是函式的基本知識了。我們來讓你的知識更進一步。在 python 中我們可以在乙個函式中定義另乙個函式:

那現在我們知道了可以在函式中定義另外的函式。也就是說:我們可以建立巢狀的函式。現在你需要再多學一點,就是函式也能返回函式。

其實並不需要在乙個函式裡去執行另乙個函式,我們也可以將其作為輸出返回出來:

再次看看這個**。在 if/else 語句中我們返回 greet 和 welcome,而不是 greet() 和 welcome()。為什麼那樣?這是因為當你把一對小括號放在後面,這個函式就會執行;然而如果你不放括號在它後面,那它可以被到處傳遞,並且可以賦值給別的變數而不去執行它。 你明白了嗎?讓我再稍微多解釋點細節。

當我們寫下 a = hi(),hi() 會被執行,而由於 name 引數預設是 yasoob,所以函式 greet 被返回了。如果我們把語句改為 a = hi(name = "ali"),那麼 welcome 函式將被返回。我們還可以列印出 hi()(),這會輸出now you are in the greet() function

現在你已經具備所有必需知識,來進一步學習裝飾器真正是什麼了。裝飾器讓你在乙個函式的前後去執行**。

你看明白了嗎?我們剛剛應用了之前學習到的原理。這正是 python 中裝飾器做的事情!它們封裝乙個函式,並且用這樣或者那樣的方式來修改它的行為。現在你也許疑惑,我們在**裡並沒有使用 @ 符號?那只是乙個簡短的方式來生成乙個被裝飾的函式。這裡是我們如何使用 @ 來執行之前的**:

希望你現在對 python 裝飾器的工作原理有乙個基本的理解。如果我們執行如下**會存在乙個問題:

print(a_function_requiring_decoration.__name__)

# output: wrapthefunction

這並不是我們想要的!ouput輸出應該是"a_function_requiring_decoration"。這裡的函式被warpthefunction替代了。它重寫了我們函式的名字和注釋文件(docstring)。幸運的是python提供給我們乙個簡單的函式來解決這個問題,那就是functools.wraps。我們修改上乙個例子來使用functools.wraps:

現在好多了。我們接下來學習裝飾器的一些常用場景。

藍本規範:

注意:@wraps接受乙個函式來進行裝飾,並加入了複製函式名稱、注釋文件、引數列表等等的功能。這可以讓我們在裝飾器裡面訪問在裝飾之前的函式的屬性。

現在我們來看一下裝飾器在哪些地方特別耀眼,以及使用它可以讓一些事情管理起來變得更簡單。

裝飾器能有助於檢查某個人是否被授權去使用乙個web應用的端點(endpoint)。它們被大量使用於flask和django web框架中。這裡是乙個例子來使用基於裝飾器的授權:

日誌是裝飾器運用的另乙個亮點。這是個例子:

我敢肯定你已經在思考裝飾器的乙個其他聰明用法了。

來想想這個問題,難道@wraps不也是個裝飾器嗎?但是,它接收乙個引數,就像任何普通的函式能做的那樣。那麼,為什麼我們不也那樣做呢? 這是因為,當你使用@my_decorator語法時,你是在應用乙個以單個函式作為引數的乙個包裹函式。記住,python裡每個東西都是乙個物件,而且這包括函式!記住了這些,我們可以編寫一下能返回乙個包裹函式的函式。

我們回到日誌的例子,並建立乙個包裹函式,能讓我們指定乙個用於輸出的日誌檔案。

現在我們有了能用於正式環境的logit裝飾器,但當我們的應用的某些部分還比較脆弱時,異常也許是需要更緊急關注的事情。比方說有時你只想打日誌到乙個檔案。而有時你想把引起你注意的問題傳送到乙個email,同時也保留日誌,留個記錄。這是乙個使用繼承的場景,但目前為止我們只看到過用來構建裝飾器的函式。

幸運的是,類也可以用來構建裝飾器。那我們現在以乙個類而不是乙個函式的方式,來重新構建logit。

這個實現有乙個附加優勢,在於比巢狀函式的方式更加整潔,而且包裹乙個函式還是使用跟以前一樣的語法:

@logit()

def myfunc1():

pass

現在,我們給 logit 建立子類,來新增 email 的功能(雖然 email 這個話題不會在這裡展開)。

從現在起,@email_logit 將會和 @logit 產生同樣的效果,但是在打日誌的基礎上,還會多傳送一封郵件給管理員。

其次,大家有興趣的話,可以看一下這篇,也是介紹的很清晰,但是有些內容確實感覺有點繁瑣,但是真正講裝飾器部分只是講了一點點:

下次再去自己總結歸納,感覺一下子有點記不住,但是學東西還是要自己反思總結比較好,下次寫第三篇,關於自己的理解部分。

python裝飾器 函式裝飾器,類裝飾器

只要實現此 模式,這個obj就叫乙個裝飾器 參考 函式裝飾器 例子 def decorator func def inner args,kwargs print before.res func args,kwargs print after.return res return inner decor...

python 裝飾器 函式裝飾器 類裝飾器

python函式裝飾器和類裝飾器筆記.usr bin env python coding utf 8 author ivan file decorators.py version from functools import wraps 裝飾器 目的是為了給函式新增附加功能 1.不帶引數裝飾器 此方式...

python裝飾器 裝飾器工廠函式

使用裝飾器實現如下所示的列印 小白聯盟def printequel func1 def inner1 print 15 func1 return inner1 def printstar func2 def inner2 print 15 func2 return inner2 printequel...