Python中裝飾器的基本概念和用法

dicksonjyl560101發表於2019-06-11


2019-06-10 11:30:47

回顧

在Python進階記錄之基礎篇(十二)中,我們介紹了高階函式的基本概念以及Python中的幾個常用高階函式,需要重點掌握map( )函式、reduce( )函式、filter( )函式和sorted( )函式的區別和用法。今天我們講一下Python中的裝飾器。

裝飾器的概念與意義

裝飾器是Python特有的一大特色,要學習併入門Python,裝飾器是一道不得不跨越的坎。裝飾器本質上是一個Python函式,它可以讓其他函式在不需要做任何程式碼變動的前提下增加額外功能,裝飾器的返回值也是一個函式物件。

裝飾器的建立

我們知道,Python中函式也是一個物件,並且可以被直接賦值給變數,同時透過變數也能呼叫該函式。

Python中裝飾器的基本概念和用法

函式

上述程式碼中,我們將say( )函式賦值給變數f,那麼f也是一個函式,並且函式名跟函式功能與say( )函式完全一致。

現在,我們要對say( )函式做一個擴充套件,例如每次呼叫print語句前列印當前時間。我們可以直接透過修改say( )函式來實現這一需求。(以下程式碼中,列印當前時間我們使用了Python中內建的time模組,日後講解模組時再詳細介紹。)

Python中裝飾器的基本概念和用法

print語句前列印當前時間

以上是透過修改say( )函式的定義來實現需求的,但在專案開發中,尤其是多人協作的大型專案,修改他人定義的函式可能會導致修改錯誤而影響專案的正常運轉。因此,有時我們並不希望修改函式定義,此時裝飾器就登場了。

本質上,裝飾器就是一個返回函式的高階函式。下面,我們建立一個列印當前時間的簡單的裝飾器。

Python中裝飾器的基本概念和用法

簡單裝飾器

上述程式碼中,log( )函式就是一個簡單的裝飾器。可以看到,它接收一個函式,並且返回值也是函式。裝飾器裡面的wrapper( )函式是整個裝飾器的核心,它返回接收的函式say( )函式,這樣我們就可以在say( )函式呼叫前實現列印當前時間的需求了。

對於裝飾器,Python同時支援@語法糖的寫法,從而簡便了裝飾器的使用。

Python中裝飾器的基本概念和用法

@語法糖使用裝飾器

@語法糖的寫法就是在@後面跟上裝飾器的名稱,然後放在要使用裝飾器的函式定義上面。此時我們再次呼叫say( )函式,它就會自動去呼叫裝飾器了。

帶引數的裝飾器

在上述裝飾器中,我們看到,wrapper( )函式的引數格式為(*args, **kwargs),因此,wrapper( )函式可以接收任意引數,即呼叫裝飾器的函式可以使用任意引數。

Python中裝飾器的基本概念和用法

wrapper()函式接收引數

裝飾器本身也支援傳入引數,不過要實現裝飾器本身傳參,裝飾器內部就需要編寫一個返回裝飾器的高階函式,寫出來會更加複雜。

Python中裝飾器的基本概念和用法

裝飾器本身帶引數

上述程式碼中,裝飾器本身傳入了一個name引數,整個裝飾器就變成了3層巢狀。從結構上看,這個裝飾器中的wrapper( )函式單獨拿出來就是一個不帶引數的裝飾器。因此,裝飾器本身要傳參,其實就是在不帶引數的裝飾器外再加一層巢狀,將要傳入的引數傳入即可。

總結

以上內容介紹了Python中裝飾器的基本概念和用法,需要重點掌握裝飾器的建立、傳參以及作用,裝飾器的作用就是為已經存在的函式或物件新增額外的功能。裝飾器在我們使用Python進行專案開發時會大量使用到,尤其是用於有切面需求的場景,比如插入日誌、效能測試、快取等。有了裝飾器,我們就可以抽離出大量與函式功能本身無關的雷同程式碼並繼續重用。感謝大家的支援與關注,歡迎一起學習交流~


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29829936/viewspace-2647264/,如需轉載,請註明出處,否則將追究法律責任。

相關文章