91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何使用Python裝飾器Decorator

發布時間:2021-10-19 17:57:37 來源:億速云 閱讀:138 作者:iii 欄目:編程語言

本篇內容介紹了“如何使用Python裝飾器Decorator”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

 1. 疊加使用Python裝飾器

最近有學員問,Python中也有與Java類似的@xxxx語法,這到底是什么意思呢?現在我就來回答這個問題。

Java中的@xxxx語法是注解(Annotation),而Python中的@xxxx語法是裝飾器(decorator),盡管在語法上類似,但作用完全不同。Java的注解相當于語法元素(方法、類、接口等)的元數據。而Python的裝飾器是對Python函數(方法)的包裝,現在我們來舉個例子。

@makebold @makeitalic def say():    return "Hello" print(say()))

這段代碼,對函數say使用了2個裝飾器:@makebold和@makeitalic,而且是疊加狀態。@makeitalic會首先作用于say函數,然后@makebold會作用于@makeitalic裝飾器的結果,這兩個裝飾器分別用......包裝say函數返回的字符串,所以這段代碼的執行結果如下:

Hello

不過直接執行這段代碼肯定會出錯的,這是因為這兩個裝飾器還沒定義,下面就看下如何定義這兩個裝飾器。

2. 定義Python裝飾器

裝飾器本身就是一個普通的Python函數,只是函數的參數需要是函數類型(通常傳入被裝飾的函數),定義形式如下:

<b><i>Hello</i></b>

現在就來定義前面給出的兩個裝飾器:

from functools import wraps  def makebold(fn):     @wraps(fn)     def makebold_wrapped(*args, **kwargs):         return "<b>" + fn(*args, **kwargs) + "</b>"     return makebold_wrapped  def makeitalic(fn):     @wraps(fn)     def makeitalic_wrapped(*args, **kwargs):         return "<i>" + fn(*args, **kwargs) + "</i>"     return makeitalic_wrapped

很明顯,makebold和makeitalic是兩個普通的Python函數,而且在函數內部分別定義了另外兩個函數,而且這兩個函數被作為返回值返回。這其中使用了wraps函數,這個函數其實可以不加,不過會有一些副作用。

由于使用@makebold和@makeitalic修飾某個函數時,會將這個被修飾的函數傳入makebold函數和makeitalic函數,也就是說,fn參數就是這個被修飾的函數。而在外部調用這個被修飾函數時,實際上是調用了修飾器返回的函數,也就是makebold_wrapped和makeitalic_wrapped,這樣就會導致被修飾函數屬性的改變,如函數名、函數文檔等,現在可以先去掉@wraps,執行下面的代碼:

@makeitalic @makebold def say():    return "Hello" print(say.__name__)   # 輸出函數名

會輸出如下的內容:

makebold_wrapped

由于最后使用了@makebold裝飾器,所以輸出的是makebold函數返回的makebold_wrapped函數的名字。如果加上@wraps,那么就會輸出say。

要注意,需要通過裝飾器方式調用wraps函數,這樣其實就相當于在@makebold外面又包了一層裝飾器(wraps)。

3. 理解Python函數

現在我們已經了解了如何自定義Python裝飾器,但應該如何理解裝飾器呢?到底是什么原理呢?要想理解Python裝飾器,首先應該知道Python函數就是對象,看下面的例子:

def shout(word="yes"):     return word.capitalize() # 輸出:Yes print(shout()) # 將shout函數賦給另一個變量,這里并沒有使用圓括號, # 所以不是調用函數,而是將函數賦給另一個變量,也就是為函數起一個別名 scream = shout  # 可以用scream調用shout函數 # 輸出:Yes print(scream())  # 目前,同一個函數,有兩個引用:scream和shout,可以使用del刪除一個引用 del shout try:     # 該引用刪除后,就不能通過該引用調用函數了     print(shout()) except NameError as e:     print(e)  # 仍然可以通過另外一個引用調用函數 # 輸出:Yes print(scream())

這段代碼演示了把函數作為對象使用。如果加一對圓括號,就是調用函數,如果不加一對圓括號,函數就是對象,可以賦給另一個變量,也可以作為函數參數值傳入函數。

由于Python函數本身是對象,所以可以在任何地方定義,包括函數內容,這就是Python內建函數,代碼如下:

def talk():     # 內嵌函數     def whisper(word="YES"):         return word.lower()+"..."      # 調用內嵌函數     print(whisper())  # 調用talk,whisper函數在talk內部被調用 # 輸出:yes... talk()  try:     # 但whisper函數在talk函數外部并不可見,所以調用會哦拋出異常     print(whisper()) except NameError as e:     print(e)

現在來總結下,Python函數的特性如下:

(1)可以將函數本身賦給一個變量,或作為參數值傳入函數(方法);

(2)可以在一個函數(方法)內部定義;

有了這兩個特性,就意味著函數可以被另一個函數返回,看下面的代碼:

def getTalk(kind="shout"):      #  定義第1個內嵌函數     def shout(word="yes"):         return word.capitalize()+"!"     # 定義第2個內嵌函數     def whisper(word="yes") :         return word.lower()+"..."      # 根據參數值返回特定的函數     if kind == "shout":         # 這里沒有使用一對圓括號,所以不是調用函數,而是返回函數本身         return shout     else:         return whisper   # talk是函數本身,并沒有被調用 talk = getTalk()  # 輸出函數本身 # 輸出:<function getTalk.<locals>.shout at 0x7f93a00475e0> print(talk)  # 調用talk函數(其實是shout函數) print(talk()) #outputs : Yes!  # 調用whisper函數 print(getTalk("whisper")())

在這段代碼中,getTalk函數根據kind參數的值返回不同的內嵌函數,所以getTalk函數的返回值是函數本身,或稱為函數對象,如果要調用函數,需要使用一對圓括號,如getTalk()()。

根據這一特性,我們還可以做更多事,例如,在調用一個函數之前自動完成其他工作,看下面的代碼:

def doSomethingBefore(func):     print("I do something before then I call the function you gave me")     print(func())  doSomethingBefore(talk)

其實這段代碼用doSomethingBefore函數包裝了talk,這樣可以通過doSomethingBefore函數調用talk函數,并在調用talk函數之前輸出一行文本。

4. Python裝飾器的原理

理解了Python函數,再理解Python裝飾器就容易得多了。廢話少說,先看下面的代碼:

# 裝飾器函數,參數是另一個函數(被裝飾的函數) def my_shiny_new_decorator(a_function_to_decorate):     # 裝飾器的內嵌函數,用來包裝被修飾的函數     def the_wrapper_around_the_original_function():         # 在調用被修飾函數之前輸出一行文本         print("Before the function runs")          # 調用被裝飾函數         a_function_to_decorate()          # 在調用被修飾函數之后輸出一行文本         print("After the function runs")      # 返回包裝函數     return the_wrapper_around_the_original_function  # 這個函數將被my_shiny_new_decorator函數修飾 def a_stand_alone_function():     print("I am a stand alone function, don't you dare modify me")  # 調用函數 a_stand_alone_function()  # 修飾a_stand_alone_function函數 a_stand_alone_function_decorated = my_shiny_new_decorator(a_stand_alone_function) a_stand_alone_function_decorated()

執行這段代碼,會輸出如下內容:

I am a stand alone function, don't you dare modify me Before the function runs I am a stand alone function, don't you dare modify me After the function runs

在這段代碼中,通過my_shiny_new_decorator函數修飾了a_stand_alone_function函數,并在調用a_stand_alone_function函數前后各輸出了一行文本。其實這就是Python裝飾器的作用:包裝函數。只是這里并沒有使用裝飾器的語法,而是用了最樸素的方式直接調用了裝飾器函數來修飾a_stand_alone_function函數。

如果用裝飾器來修飾a_stand_alone_function函數,那么可以用下面的代碼。

@my_shiny_new_decorator def a_stand_alone_function():     print("I am a stand alone function, don't you dare modify me")

這時再調用a_stand_alone_function函數,就會自動使用my_shiny_new_decorator函數對a_stand_alone_function函數進行包裝,也就是說,@my_shiny_new_decorator是my_shiny_new_decorator(a_stand_alone_function)的簡寫形式。

“如何使用Python裝飾器Decorator”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

泰顺县| 龙南县| 大同县| 德保县| 松阳县| 黔江区| 城口县| 惠水县| 华阴市| 高台县| 东宁县| 铁岭市| 荔波县| 石狮市| 汾西县| 陇南市| 宁波市| 商南县| 泰来县| 大理市| 宜兰市| 清新县| 黄龙县| 吉林市| 巫溪县| 津南区| 米泉市| 杂多县| 女性| 卢龙县| 呼和浩特市| 富阳市| 伊春市| 伊金霍洛旗| 盱眙县| 清原| 革吉县| 绿春县| 通城县| 永泰县| 米泉市|