Python裝飾器的調用過程

Python裝飾器的調用過程

  在Python學習的過程當中,裝飾器是比較難理解的一個應用。本人也在學習期間也遇到不少坑,現將裝飾器的基本調用過程總結一下。閉包

  首先,裝飾器用到了「閉包」,而「閉包」是學習裝飾器的基礎,因此在講裝飾器以前先將「閉包」的基本概念帶你們一塊兒回顧一下:函數

  現有以下函數:學習

def func():
    def func1():
        print('i\'m func1')
    return func1
if __name__ == '__main__':   f
= func()
  f()
  print('函數func1的內存地址爲:',f)

  咱們在函數func()內部定義了另一個函數func1(),最終return的是func1的內存地址。 spa

  函數定義完後,在全局把func()賦值給變量f,此時f中拿到的是func1的內存地址,這時候你能夠把f當作是func1,進行f()操做至關於調用func1(),因此上面代碼的輸出結果爲:code

 

  此時有些人可能會問:既然f至關於func1,那麼爲什麼不在全局中直接調用func1()呢?答案是不行~由於func1()是在全局的函數func()裏面定義的,全局狀況下只能調用func(),不能夠直接調用func()裏面的函數:blog

  這裏咱們能夠看到:"func1 is not defined",由於在全局程序只能調用func(),是找不到func1()的,跟別提調用了。內存

  因此,咱們要想在全局狀況下調用「全局函數」內部定義的函數,就必須令該全局函數返回「內部函數」的內存地址,而後將該內存地址賦值給一個變量,經過調用這個變量來實現「全局調用內部函數」,而此時,這個「內部的函數」就稱爲「閉包」class

  而上述例子中,函數func1就是一個閉包。基礎

  理解了「閉包」的概念後咱們再來看「裝飾器」的調用過程:變量

不帶參數的裝飾器

  如上圖:這裏咱們先定義了一個裝飾器Dec(),而Dec函數裏面的outer函數就是一個閉包。當咱們在函數func2定義前加上@Dec時,這個語句至關於:func2 = Dec(func2)。也就是說,咱們在進行不帶參數的裝飾器的調用時,至關於把下面的函數名當作參數傳給了@後面的函數,@Dec也就至關於執行了Dec(func2)。後面就好理解了:Dec()函數返回了outer函數的內存地址,下面的func2()其實就調用了「閉包」outer(),進行了outer()函數裏面的操做。

帶參數的裝飾器

  這裏須要注意的是:若是要返回函數的話,帶參數的裝飾器就要寫三層內嵌函數。

  帶參數的裝飾器的具體執行過程分爲兩步:首先執行Dec('QQ'),無論中間過程,Dec函數返回的是函數outer的內存地址,此時就變成了@outer,按照「不帶參數的裝飾器」的調用過程咱們知道,此時outer將函數func2的名稱當作是參數執行outer裏面的函數inner()。另外咱們還須要注意:如今inner裏不只有func2,還有Dec自己所攜帶的參數'QQ'。

  此外:打印出來的"i'm inner"是在斷定if type == 'QQ'後直接執行的;而"i'm func2"是inner()函數執行「outer函數所帶的參數」調用的結果,也就是說inner函數最後調用了「outer函數所帶的參數」func並執行了它,換句話講,inner就是一個閉包。

相關文章
相關標籤/搜索