成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

Python中的閉包與裝飾器是什么

這篇文章將為大家詳細(xì)講解有關(guān)Python中的閉包與裝飾器是什么,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

創(chuàng)新互聯(lián)公司是一家集網(wǎng)站設(shè)計制作、成都網(wǎng)站建設(shè)、網(wǎng)站頁面設(shè)計、網(wǎng)站優(yōu)化SEO優(yōu)化為一體的專業(yè)的建站公司,已為成都等多地近百家企業(yè)提供網(wǎng)站建設(shè)服務(wù)。追求良好的瀏覽體驗,以探求精品塑造與理念升華,設(shè)計最適合用戶的網(wǎng)站頁面。 合作只是第一步,服務(wù)才是根本,我們始終堅持講誠信,負(fù)責(zé)任的原則,為您進行細(xì)心、貼心、認(rèn)真的服務(wù),與眾多客戶在蓬勃發(fā)展的市場環(huán)境中,互促共生。

函數(shù)的裝飾器可以以某種方式增強函數(shù)的功能,如在 Flask 中可使用 @app.route('/') 為視圖函數(shù)添加路由,是一種十分強大的功能。在表現(xiàn)形式上,函數(shù)裝飾器為一種嵌套函數(shù),這其中會涉及到閉包的概念。而在嵌套函數(shù)之間,外部函數(shù)中的變量相對于內(nèi)部函數(shù)而言為自由變量,使用時可能需要借助于 nonlocal 關(guān)鍵字進行聲明。

nonlocal 聲明

按變量的作用域進行分類,Python 中的變量可分為「全局變量」、「局部變量」以及「自由變量」。一般而言,Python 中使用變量前不需要聲明變量,但假定在函數(shù)體中賦值的變量為局部變量~除非顯示使用 global 將在函數(shù)中賦值的變量聲明為全局變量!

而自由變量則是存在于嵌套函數(shù)中的一個概念~定義在其他函數(shù)內(nèi)部的函數(shù)被稱之為嵌套函數(shù) nested function ,嵌套函數(shù)可以訪問封閉范圍內(nèi)(外部函數(shù))的變量。嵌套函數(shù)不可以在函數(shù)外直接訪問。

在 Python 中,非本地變量默認(rèn)僅可讀取,在修改時必須顯式指出其為非本地變量~自由變量 nonlocal,全局變量 global。

>>> ga = 1
>>> def func():
...     nb = 2
...     def inner():
...         ga += 1
...         nb += 2
...         print('ga is %s, and nb is %s' % (ga, nb))
...     return inner
...
>>> test = func()
Traceback (most recent call last):
...
UnboundLocalError: local variable 'ga' referenced before assignment

未加入全局變量和自由變量聲明時且使用賦值操作時,inner 函數(shù)的變量 ga, nb 默認(rèn)為局部變量,會報錯;如注釋掉 ga += 1 后同樣會報錯:

Traceback (most recent call last):
...
UnboundLocalError: local variable 'nb' referenced before assignment

可行改寫如下:

>>> ga = 1
>>> def func():
...     nb = 2
...     def inner():
...         global ga
...         nonlocal nb
...         ga += 1
...         nb += 2
...         print('ga is %s, and nb is %s' % (ga, nb))
...     return inner
...
>>> test = func()
>>> test()
ga is 2, and nb is 4
>>> test()
ga is 3, and nb is 6

通過顯示聲明 ga, nb 分別為「全局變量」和「自由變量」,此時如預(yù)期運行!

閉包

函數(shù)內(nèi)的函數(shù)以及其自由變量形成閉包。也即閉包是一種保留定義函數(shù)時存在的自由變量的綁定的函數(shù)~這樣在調(diào)用函數(shù)時,綁定的自由變量依舊可用。

閉包可以避免全局變量的使用以及提供某種形式的數(shù)據(jù)隱藏。當(dāng)函數(shù)中的變量和函數(shù)較少且其中某個功能常用時,使用閉包來進行封裝。當(dāng)變量和函數(shù)更加復(fù)雜時,則使用類來實現(xiàn)。

# 計算移動平均值的函數(shù)
def make_averager():
    series = []

    def averager(new_value):
        series.append(new_value)
        total = sum(series)
        return total/len(series)

    return averager

那么此時,make_averager() 函數(shù)的第二行 series = [] 到第七行 return total/len(series) 為閉包,變量 series 為 averager() 函數(shù)中的自由變量!

# avg 為一個 averager 函數(shù)對象 ~ 含自由變量的綁定
>>> avg = make_averager()
>>> avg(10)
10.0
>>> avg(11)
10.5
>>> avg(12)
11
# 創(chuàng)建另一個 averager 函數(shù)對象
>>> avg2 = make_averager()
>>> avg2(1)
1.0
>>> avg2(18)
9.5
# 查看 avg, avg2 自由變量中保存的值
>>> avg.__closure__[0].cell_contents
[10, 11, 12]
>>> avg2.__closure__[0].cell_contents
[1, 18]

函數(shù)對象通過 __closure__ 屬性 —— 返回 cell 對象元祖(函數(shù)中有多少嵌套函數(shù)則該元祖的長度有多長),生成該對象的函數(shù)被稱之為閉包函數(shù)。

func.__closure__[0].cell_contents: 訪問存儲在 cell 對象中值。

裝飾器

裝飾器本身是一個可調(diào)用的對象~函數(shù)或類,其參數(shù)為另一個函數(shù)(被裝飾的函數(shù))。裝飾器可能會處理被裝飾的函數(shù)(如添加一些功能)然后將之返回,或者將之替換為另一個函數(shù)或可調(diào)用對象。這也被稱之為元編程 metaprogramming —— 在編譯時改變函數(shù)功能。

>>> def make_pretty(func):
...     def inner():
...         print("I got decorated!", end='\t')
...         func()
...     return inner
...
>>> def ordinary():
...     print("I am ordinary!")

# 用 make_pretty 函數(shù)裝飾 ordinary 函數(shù)
>>> pretty = make_pretty(ordinary)
>>> pretty()
I got decorated!  I am ordinary!

可以作為裝飾器的函數(shù)內(nèi)部都有嵌套的功能函數(shù)(用以實現(xiàn)主要功能),并返回內(nèi)部的嵌套函數(shù)。

@make_pretty
def ordinary():
    print("I am ordinary!")

# 等價于
def ordinary():
    print("I am ordinary!")
ordianry = make_pretty(ordinary)

make_pretty(func) 是一個最簡單的裝飾器,它接受一個函數(shù)為其參數(shù);內(nèi)部定義了一個 inner() 函數(shù)~輸出 "I got decorated!" 后執(zhí)行被裝飾函數(shù)(此時 func 為 inner 閉包中的自由變量);然后返回內(nèi)部函數(shù) inner。

此時,對于被裝飾的函數(shù) ordinary 而言,此時是 inner 的引用:

>>> ordinary()
I got decorated!  I am ordinary!
>>> ordinary
<function make_pretty.<locals>.inner at 0x10aeaa1e0>

除了最簡單的裝飾器之外,還可以將多個裝飾器疊放使用

疊放裝飾器

def star(func):
    def inner(*args, **kwargs):
        print('*' * 30)
        func(*args, **kwargs)
        print('*' * 30)
    return inner

def dollar(func):
    def inner(*args, **kwargs):
        print('$' * 30)
        func(*args, **kwargs)
        print('$' * 30)
    return inner

@star
@doller
def printer(msg):
    print(msg)

printer("Hello world!")

# 結(jié)果如下
'''
******************************
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
Hello world!
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
******************************
'''

# 等價于
def printer(msg):
    print(msg)
printer = star(dollar(printer))

關(guān)于Python中的閉包與裝飾器是什么就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

網(wǎng)頁標(biāo)題:Python中的閉包與裝飾器是什么
新聞來源:http://jinyejixie.com/article12/ijdodc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供用戶體驗、域名注冊外貿(mào)網(wǎng)站建設(shè)、關(guān)鍵詞優(yōu)化、移動網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站托管運營
奉化市| 富宁县| 南开区| 海兴县| 手游| 南京市| 临颍县| 陆川县| 凤山县| 沈丘县| 赤城县| 板桥市| 宜良县| 南澳县| 鄂托克前旗| 沙洋县| 五台县| 禄劝| 北碚区| 育儿| 凤冈县| 嘉兴市| 雷波县| 德清县| 宣恩县| 正宁县| 青龙| 景德镇市| 攀枝花市| 娱乐| 江永县| 墨竹工卡县| 邳州市| 上高县| 凌云县| 即墨市| 凌源市| 清水河县| 浦东新区| 承德市| 岳阳县|