理解python函式裝飾器 decorator

2021-10-02 05:46:52 字數 3571 閱讀 4449

函式裝飾器是python有別於其他語言的主要特徵之一,這也是充分發揮了動態語言的優勢,可以使我們在編寫程式時更加簡潔。但最開始接觸函式裝飾器有點難以理解,本文盡量用簡單的語言來理解函式裝飾器。

在理解函式裝飾器之前,最好儲備並理解了以下python的基礎知識:

生活中,化妝可能是最容易理解裝飾行為的例子之一。

女人化妝,就是用化妝品來裝飾女人,然後這個女人還是這個女人,並沒有根本上的改變,只是被裝飾了,更好看或者更醜了而已。可以理解為女人被化妝品包裹了,或者裝飾了。

上面的例子中,女人和化妝品都看做是物,而不是行為,不符合要完成函式功能的意義。女人和化妝品更像是類的例項,下面的生活中的例子更接近函式:

def 散步():

pass

def 聽歌():

pass

上面定義了兩個行為(函式),散步和聽歌。按照女人和化妝品的例子,我想讓散步的行為不那麼枯燥,用聽歌()行為來裝飾散步()行為。於是,就可以在散步中聽歌,然而散步依然是散步,並沒有根本上改變,只是在散步的時候增加了聽歌。散步行為用聽歌行為來進行裝飾了,或者被聽歌函式包裹了。

用偽**來表示這個裝飾行為:

散步=聽歌裝飾的(散步)

在賦值符號「=」號右邊是被聽歌行為裝飾了的散步行為,或者說被聽歌函式包裹了。同時,將裝飾的結果賦值給散步,使得散步依然是散步,只是在散步的同時增加了聽歌行為。

下面,我們來實現 散步=聽歌裝飾的(散步) 這個偽**:

# 定義散步函式

def 散步():

print

("這是散步行為"

)# 定義聽歌函式,並接受函式作為形參

def 聽歌(function)

:print

("這是聽歌行為"

)return function

# 開始用聽歌裝飾散步,並賦值給散步

散步=聽歌(散步)

# 執行散步

散步()

#output:

#這是聽歌行為

#這是散步行為

注意:上面的**可以複製後直接執行。python3支援中文變數名。

散步行為通過聽歌行為裝飾過後,就增加了聽歌的功能。

上述**也可以用python的裝飾器的形式表示,加上「@」。如下:

# 定義聽歌函式,並接受函式作為形參

def 聽歌(function)

:print

("這是聽歌行為"

)return function

# 開始裝飾

# 定義散步函式

@聽歌def 散步():

print

("這是散步行為"

)# 執行散步函式

散步()

#output:

#這是聽歌行為

#這是散步行為

可以看出,通過@符號進行裝飾後的,效果和「散步=聽歌(散步)」是一樣的,這就是python裝飾器的本質,只不過python用「@」符號進行了簡化。

但是,請注意!!!上面的例子並不是完整的裝飾器,裝飾的過程是有問題的,只是為了簡化理解而舉例的。那麼,問題在**呢?請接著看第三節。

可能你已經發現了,在裝飾的過程中(也就是 「散步=聽歌(散步) 」過程中,或者「@聽歌」過程中,兩者是一樣的),聽歌函式會執行

print

("這是聽歌行為"

)

這行**。

也就是說,output中的「這是聽歌行為」是在裝飾過程中執行輸出的,並不是裝飾完成過後,由新的 散步()函式來執行輸出的。這樣顯然是與我們現實中的裝飾的含義不一致的,這是有問題的。下面,就此問題進行改進:

# 定義聽歌函式,並接受函式作為形參

def 聽歌裝飾器(function)

:def 聽歌():

print

("這是聽歌行為"

) function(

)return 聽歌

# 開始裝飾

# 定義散步函式

@聽歌裝飾器

def 散步():

print

("這是散步行為"

)# 執行散步函式

散步()

#output:

#這是聽歌行為

#這是散步行為

上面**中,我們將聽歌行為封裝在聽歌裝飾器裡面,然後用聽歌裝飾器去裝飾散步行為。上述**的本質依然是:散步=聽歌裝飾器(散步),只不過用「@」符號進行簡化。

在聽歌裝飾器(function)裡面,將聽歌行為封裝並返回賦值給散步行為,完成了完整的裝飾過程。理解了上面的內容,就理解了python裝飾器的裝飾過程。

我們在編寫**的過程中,在執行某個函式時,會遇到在執行函式之前或之後同時執行其他一些功能函式,這也可以用裝飾器來進行簡化,達到**復用的目的,讓**更加簡潔。看下面的例子:

def

training_decorator

(f):

defchange_sportswear()

:print

("change sportswear"

)def

bathe()

:print

("bathe"

)def

decorator()

: change_sportswear(

) f(

) bathe(

)return decorator

@training_decorator

deftraining()

:print

("training"

)training(

)#output:

'''change sportswear

training

bathe

'''

上述**中,函式training()通過裝飾器training_decorator後,在執行前和執行後都完成了一些函式的功能,比如change_sportswear()和bathe()。

def

user_authentication

(function)

:pass

@user_authentication

defedit_function()

:pass

@user_authentication

defadd_function()

:pass

@user_authentication

defdel_function()

:

flask和django web框架大量應用了函式裝飾器。上面的裝飾器都是用函式來進行裝飾的,python的裝飾器用法也支援用類進行裝飾,那個不在本文介紹之列,本文的重點是幫助如何理解python的函式裝飾器。裝飾器還有很多用法細節和應用場景,比如帶引數的裝飾器等等,其本質仍然是:裝飾後賦值給被裝飾的函式,此文中就不再介紹了,感興趣的自行深入學習。

python裝飾器理解 python裝飾器理解

裝飾器 在不改變原函式的 和呼叫方法的基礎上,給原函式增加額外的功能 理解宣告 為了方便理解,以下例子採用最簡潔的函式和新增的功能 給原函式新增乙個執行時間 import time def timer func def inner func return inner timer func timer...

python裝飾器 理解Python裝飾器

在python中,對於乙個函式,若想在其執行前後做點什麼,那麼裝飾器是再好不過的選擇,話不多說,上 usr bin env coding utf 8 script 01.py author howie from functools import wraps def decorator func wr...

python裝飾器理解 python裝飾器的理解

python裝飾器應該算是面試常考到的用點,之前在flask的應用中也是會常常用到,抽空仔細看書查資料理解了下裝飾器的概念,通過自己的理解記憶,應該對這個概念會有乙個大致上具體的了解。閉包說起python裝飾器,我們應該不得不談談閉包的概念。我對閉包的理解是,當函式存在巢狀,子函式呼叫了父函式的變數...