只需四步,讓你了解Python裝飾器的誕生過程

Python中的裝飾器是通過利用了函數(shù)特性的閉包實現(xiàn)的,所以在講裝飾器之前,我們需要先了解函數(shù)特性,以及閉包是怎么利用了函數(shù)特性的

1. 函數(shù)特性

python中的函數(shù)特性總的來說有以下四點:

1. 函數(shù)作為變量傳遞

def add(x):
    return x + 1

a = add                    # 作為變量

說明:函數(shù)如果不加括號,是不會執(zhí)行的,代表的是一個函數(shù)對象,它是可以作為變量來傳遞

2. 函數(shù)作為參數(shù)傳遞

def add(x):
    return x + 1

def execute(f):
    return f(3)

execute(add)                # 作為參數(shù)

說明:一個函數(shù)可以接受另一個函數(shù)對象作為自己的參數(shù),并對函數(shù)對象進行處理

3. 函數(shù)作為返回值

def add(x):
    return x + 1

def get_add():
    return add             # 作為返回值

說明:一個函數(shù)的返回值可以是另一個函數(shù)對象

4. 函數(shù)嵌套及跨域訪問

def outer():
    x = 1
    def inner():
        print(x)         # 被嵌套函數(shù)inner內部的x變量可以到封裝域去獲取
    inner()

outer()

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

2. 閉包的實現(xiàn)

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

def outer(x):
    def inner():                  # 函數(shù)嵌套
        return x                  # 跨域訪問,引用了外部變量x

    return inner                  # 函數(shù)作為返回值

closure = outer('外部變量')        # 函數(shù)作為變量賦給closure
print(closure())                  # 執(zhí)行閉包

執(zhí)行結果:

外部變量

說明:我們分析下這個流程,outer接收到'外部變量',傳給inner,作為它return的參數(shù),最后outer返回inner函數(shù),返回的inner函數(shù)作為變量傳遞給closure,最后執(zhí)行closure這個函數(shù)對象,實際上是執(zhí)行了inner這個函數(shù),返回了 '外部變量',這樣就實現(xiàn)了一個簡單的閉包

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

下面我們來改寫一下實現(xiàn)閉包的代碼:

def func():
    return '函數(shù)func'

def outer(x):
    def inner():                              # 函數(shù)嵌套
        return '戴了inner牌帽子的 ' + x()       # 跨域訪問,引用了外部變量x

    return inner                              # 函數(shù)作為返回值

closure = outer(func)                         # 函數(shù)func作為outer的參數(shù);函數(shù)作為變量賦給closure

print(func())                                 # 執(zhí)行原始函數(shù)
print(closure())                              # 執(zhí)行閉包

執(zhí)行結果:

函數(shù)func
戴了inner牌帽子的 函數(shù)func

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

劃重點來了?。。。。。。。。。?!

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

3. 裝飾器語法糖 @

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

具體實現(xiàn)如下:

def outer(x):
    def inner():
        return '戴了inner牌帽子的 ' + x()

    return inner

@outer
def func():
    return '函數(shù)func'

print(func())

執(zhí)行結果:

戴了inner牌帽子的 函數(shù)func

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

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

關注公眾號【克里斯手冊】,了解更多數(shù)據(jù)相關的內容


本文由mdnice多平臺發(fā)布

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容