關(guān)于Python作用域的知識(shí)在python作用域有相應(yīng)的筆記,這個(gè)筆記是關(guān)于Python閉包及其作用域的詳細(xì)的筆記
如果在一個(gè)內(nèi)部函數(shù)里,對(duì)一個(gè)外部作用域(但不是全局作用域)的變量進(jìn)行引用,那么內(nèi)部函數(shù)就被稱為閉包(closure),而這個(gè)被內(nèi)部函數(shù)引用的變量則被成為自由變量
閉包和函數(shù)調(diào)用沒多少相關(guān),而是關(guān)于使用定義在其他作用域的變量
命名空間和作用域
我們把命名空間看做一個(gè)大型的字典類型(Dict),里面包含了所有變量的名字和值的映射關(guān)系。在 Python 中,作用域?qū)嶋H上可以看做是“在當(dāng)前上下文的位置,獲取命名空間變量的規(guī)則”。在 Python 代碼執(zhí)行的任意位置,都至少存在三層嵌套的作用域:
最內(nèi)層作用域,最先搜索,包含所有局部變量(Python 默認(rèn)所有變量聲明均為局部變量)
所有包含當(dāng)前上下文的外層函數(shù)的作用域,由內(nèi)而外依次搜索,這里包含的是非局部也非全局的變量
一直向上搜索,直到當(dāng)前模塊的全局變量
最外層,最后搜索的,內(nèi)置(built-in)變量
scopes = { "local": {"locals": None, "non-local": {"locals": None, "global": {"locals": None, "built-in": ["built-ins"]}}},}除了默認(rèn)的局部變量聲明方式,Python還有g(shù)lobal和nonlocal兩種類型的聲明(nonlocal是Python3.x之后才有的),其中nonlocal是指最內(nèi)層之外,global以內(nèi)的變量。必須強(qiáng)調(diào)的是,最內(nèi)層局部作用域?qū)ν鈱幼饔糜虻淖兞恐挥兄蛔x(read-only)的訪問權(quán)限。比如下列的例子
x = 100def main(): x += 1 print (x)main()
UnboundLocalError Traceback (most recent call last)<ipython-input-2-9ed43e483a17> in <module>() 3 x += 1 4 print(x)----> 5 main()<ipython-input-2-9ed43e483a17> in main() 1 x = 100 2 def main():----> 3 x += 1 4 print(x) 5 main()UnboundLocalError: local variable 'x' referenced before assignment
這里拋出UnboundLocalError,是因?yàn)閙ain()函數(shù)內(nèi)部的作用域?qū)τ谌肿兞縳僅有只讀權(quán)限,想要在main()中對(duì)x進(jìn)行改變,不會(huì)影響全局變量,而是會(huì)創(chuàng)建一個(gè)新的局部變量,顯然無法對(duì)還未創(chuàng)建的局部變量直接使用x += 1, 因?yàn)閤未綁定到任何對(duì)象上。如果想要獲得全局變量的完全引用,則需要global聲明:
x = 100def main(): global x x += 1 print(x)main()print(x) # 全局變量已被改變# result: # 101# 101
閉包
閉包和函數(shù)調(diào)用沒多少相關(guān),而是關(guān)于使用定義在其他作用域的變量。
看了上面的Python作用域規(guī)則后,我們可以仿照J(rèn)avaScript寫一個(gè)計(jì)數(shù)器的閉包:
"""/* JavaScript Closure example */var inc = function(){ var x = 0; return function(){ console.log(x++); };};var inc1 = inc()var inc2 = inc()"""# Pythondef inc(): x = 0 def inner(): nonlocal x x += 1 print(x) return innerinc1 = inc()inc2 = inc()inc1()inc1()inc1()inc2()# result:# 1# 2# 3# 1在這里,全局環(huán)境下不能獲取到inc()中的局部變量x的,但是我們返回了inc()內(nèi)部函數(shù)inner(),而inner()對(duì)inc()中的局部變量是有訪問權(quán)限的。也就是說inner()將inc()局部作用域打包發(fā)送給了inc1和 inc2,從而使他們各自獨(dú)立擁有了一塊封閉起來的作用域,不受其他運(yùn)行環(huán)境和全局變量的影響,因此稱之為閉包。
上述代碼中inc1和inc2各自有一塊封閉起來的作用域,可以通過Online Python Tutor 可視化運(yùn)行工具看相應(yīng)的運(yùn)行結(jié)果

這篇基于Python閉包及其作用域詳解就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持武林網(wǎng)。
新聞熱點(diǎn)
疑難解答
圖片精選