當前位置:
首頁 > 知識 > Python裝飾器的誕生過程

Python裝飾器的誕生過程


程序員大咖

點擊右側關注,免費進階高級!





作者:ChrisYZX


https://www.jianshu.com/u/45eabf52c017




Python中的裝飾器是通過利用了函數特性的閉包實現的,所以在講裝飾器之前,我們需要先了解函數特性,以及閉包是怎麼利用了函數特性的。


一、函數特性


Python中的函數特性總的來說有以下四點:

1. 函數作為變數傳遞

def

 

add(x)

:


    

return

 x + 

1

a = add                    

# 作為變數



說明:函數如果不加括弧,是不會執行的,代表的是一個函數對象,它是可以作為變數來傳遞。


2.函數作為參數傳遞

def

 

add(x)

:


    

return

 x + 

1

def

 

excute(f)

:


    

return

 f(

3

)

excute(add)                

# 作為參數



說明:一個函數可以接受另一個函數對象作為自己的參數,並對函數對象進行處理。


3.函數作為返回值

def

 

add(x)

:


    

return

 x + 

1

def

 

get_add()

:


    

return

 add             

# 作為返回值


說明:一個函數的返回值可以是另一個函數對象。


4.函數嵌套及跨域訪問

def

 

outer()

:


    x = 

1


    

def

 

inner()

:


        print(x)         

# 被嵌套函數inner內部的x變數可以到封裝域去獲取


    inner()

outer()

說明:一個函數(主函數)內部是可以嵌套另一個函數(子函數)的,比如outer函數從內部嵌套了inner。一個函數本地域沒有的變數,是可以跨到它的封裝域(主函數與子函數之間的範圍)去尋找的。


二、閉包的實現


Python中的裝飾器是通過閉包實現的,簡單地講,閉包就是引用了外部變數的內部函數,而閉包的實現正是利用了以上函數特性,下面我們來看看閉包是如何實現的:

def

 

outer(x)

:


    

def

 

inner()

:

                  

# 函數嵌套


        

return

 x                  

# 跨域訪問,引用了外部變數x

    

return

 inner                  

# 函數作為返回值

closure = outer(

"外部變數"

)        

# 函數作為變數賦給closure


print(closure())                  

# 執行閉包



執行結果:

外部變數

說明:我們分析下這個流程,outer接收到"外部變數",傳給inner,作為它return的參數,最後outer返回inner函數,返回的inner函數作為變數傳遞給closure,最後執行closure這個函數對象,實際上是執行了inner這個函數,返回了 "外部變數",這樣就實現了一個簡單的閉包。


我們發現上面的閉包例子只用到了之前說的其中3個函數特性,函數作為參數 這個特性好像並沒用上,別急,我們一步步來,試想一下,outer的參數x是不是也可以是一個函數對象?


下面我們來改寫一下實現閉包的代碼:

def

 

func()

:


    

return

 

"函數func"

def

 

outer(x)

:


    

def

 

inner()

:

                              

# 函數嵌套


        

return

 

"戴了inner牌帽子的 "

 + x()       

# 跨域訪問,引用了外部變數x

    

return

 inner                              

# 函數作為返回值

closure = outer(func)                         

# 函數func作為outer的參數;函數作為變數賦給closure

print(func())                                 

# 執行原始函數


print(closure())                              

# 執行閉包



執行結果:

函數

func


戴了

inner

牌帽子的 函數

func



說明:我們看到列印的結果, 從 func() 到 closure(),我們是不是感覺函數func被裝飾了一番,變成了closure,具體是怎麼裝飾的呢?


我們看到closure實際上是outer(func),func作為參數傳進outer,outer的子函數inner對func返回的結果進行了一番裝飾,返回了一個裝飾後的結果,最後outer返回inner,可以說inner就是裝飾後的func,這就是一個函數被裝飾的過程,重點在於執行 outer(func) 這個步驟。


三、裝飾器語法糖 @


Python給我們提供了語法糖 @,我們想執行 outer(func) 的時候,只需要把outer函數@到func函數的上面就可以了。


具體實現如下:

def

 

outer(x)

:


    

def

 

inner()

:


        

return

 

"戴了inner牌帽子的 "

 + x()

    

return

 inner

@outer


def

 

func()

:


    

return

 

"函數func"

print(func())

執行結果:

戴了inner牌帽子的 函數

func


說明:我們看到列印的結果跟我們執行closure()的結果是一樣的,也就說明 加了outer裝飾器的func 等價於 outer(func),所以我們很清楚地知道裝飾器@的作用是什麼了,就是拿來把被裝飾的函數作為參數傳遞到裝飾器函數裡面加工的,最後執行被裝飾函數的時候,就相當於執行了一個加工後的函數。


以上就是Python中裝飾器的誕生過程。


【點擊成為源碼大神】

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python開發 的精彩文章:

孫悟空為什麼那麼瘦?

TAG:Python開發 |