Python嵌套函數(shù)與nonlocal使用詳細(xì)介紹
理解閉包之前,我們首先需要理解什么是嵌套函數(shù)(nested functions)以及非局部(nonloca)關(guān)鍵字
嵌套函數(shù)
- 在另一個(gè)函數(shù)中定義的函數(shù)稱為嵌套函數(shù)。
- 嵌套函數(shù)可以訪問 這個(gè)封閉范圍域內(nèi)的 變量。
- 在python中,這些非局部變量只可以在他們的作用域范圍內(nèi)訪問。
嵌套函數(shù)的例子:
#Python program to illustrate #nested functions def outerFunction(text): text = text #該函數(shù)定義在函數(shù)之內(nèi),作為一個(gè)內(nèi)部函數(shù) def innerFunction(): print(text) #out函數(shù)中,調(diào)用這個(gè)內(nèi)部函數(shù) innerFunction() if __name__ == '__main__': outerFunction('Hey !')
嵌套函數(shù)中變量的范圍
在一個(gè)函數(shù)中訪問全局變量之前已經(jīng)說過了,但是怎么在一個(gè)內(nèi)部函數(shù)中訪問外部函數(shù)的變量?
def f1(): #f1的變量 s = 'hello' def f2(): #f2()內(nèi)部使用f1的變量 print(s) f2() f1()
這種訪問方式和 函數(shù)內(nèi)訪問全局變量很類似。
現(xiàn)在我想要在內(nèi)部函數(shù)改變外部函數(shù)的變量要怎么做?
def f1(): #f1的變量 s = 'hello' def f2(): #f2()內(nèi)部試圖改變f1的變量 s = 'hi hi hi' print(s) f2() print(s) #調(diào)用f1() f1()
在f2()
內(nèi)部通過s = 'hi hi hi'
試圖將外部函數(shù)的變量值s
改變。
但是其實(shí)是在f2()
內(nèi)部重新創(chuàng)建了一個(gè)新的變量也叫s
,所以完全不會(huì)對(duì)外部的s
有影響。
這和函數(shù)內(nèi)部改變?nèi)肿兞渴穷愃频?,不?code>global,只是創(chuàng)建了一個(gè)同名變量。
那么同樣使用global
行不行?
def f1(): #f1的變量 s = 'hello' def f2(): #f2()內(nèi)部試圖使用global改變f1的變量 global s s = 'hi hi hi' #實(shí)際是在f2()中創(chuàng)建了一個(gè)全局變量 print(s) f2() print(s) #調(diào)用f1() f1()
結(jié)果是完全沒有變化的,
global s
實(shí)際上是在f2()
內(nèi)部聲明s
是一個(gè)全局變量,是整個(gè)程序都可以使用的,它和f1()
中的s
不是同一個(gè)。我們可以在函數(shù)外輸出它:
那么如何通過內(nèi)部函數(shù)改變外部函數(shù)的變量值呢?其中一種方法是使用nonlocal
關(guān)鍵字:
def f1(): #f1的變量 s = 'hello' def f2(): #f2()使用nonlocal改變f1的變量 nonlocal s s = 'hi hi hi' print(s) f2() print(s) #調(diào)用f1() f1()
在f2()函數(shù)內(nèi)部成功的修改了f1()函數(shù)中的變量s的值
nonlocal
nonlocal 關(guān)鍵字被用來在最近的范圍域中引用變量, 在局部變量和全局變量上使用不起作用,用于在全局范圍和本地局部范圍之外的另一個(gè)范圍內(nèi)引用變量。nonlocal關(guān)鍵字常常被用在嵌套函數(shù)中引用 父函數(shù)中的變量。
使用nonlocal的優(yōu)點(diǎn)
- 幫助我們?cè)L問上層作用域中的變量
- 引用的變量被重復(fù)使用,因此該變量的內(nèi)存地址也被重復(fù)適使用,所以可以將局部變量保存在內(nèi)存中
缺點(diǎn)
- nonloca關(guān)鍵字不可以用來引用全局變量和局部變量
- nonloca關(guān)鍵字只能用在嵌套結(jié)構(gòu)中
舉例
使用nonlocal關(guān)鍵字修改父函數(shù)中的變量
def foo(): name = 'hello' def bar(): nonlocal name #修改父函數(shù)的變量 name = 'hi hi' print(name) #調(diào)用bar() bar() #父函數(shù)foo()內(nèi)輸出name print(name) #調(diào)用foo() foo()
如果使用nonlocal 修改全局變量會(huì)怎么樣?
#全局變量 global_name = 'hello' #外部函數(shù) def f1(): #內(nèi)部函數(shù) def f2(): #使用nonlocal 聲明,嘗試使用nonlocal 引用全局變量 nonlocal global_name global_name = 'hi hi'#嘗試 修改 print(global_name) #掉用f2() f2() f1() print(global_name)
報(bào)錯(cuò)信息顯示:沒有叫做global_name
的nonlocal
變量,這是因?yàn)椋?/p>
nonlocal
是用在嵌套結(jié)構(gòu)中,用來引用父函數(shù)中的局部變量的,但是父函數(shù)f1()
中沒有叫做global_name
的局部變量,對(duì)于函數(shù)外部的全局變量global_name
來說,使用nonlocal
是無法引用的,所以python解釋器找不到global_name
,自然出錯(cuò)。
多層嵌套中的nonlocal
def f1(): name = 'f1' def f2(): name = 'f2' def f3(): #nonlocal 修改父函數(shù)的變量,即f2()的name nonlocal name print(name) #輸出f2 使用的是f2中的name name = 'f3' #對(duì)f2中的name修改 print(name) #輸出f3 修改成功 f3() print(name)#輸出f3,雖然是f2中的name,但是在f3中修改了 f2() print(name)#輸出f1,f1的name,沒有被使用 f1()
所以在多層嵌套的結(jié)構(gòu)成,nonlocal關(guān)鍵字會(huì)尋找最近的上層,也就是父函數(shù),而不是更上層的爺爺函數(shù)。
嵌套函數(shù)中局部變量的重用
def counter(): #c是局部變量 c = 0 def count(): #使用上層函數(shù)中的c nonlocal c c += 1 return c return count
調(diào)用外部counter()
函數(shù),正常來說,函數(shù)調(diào)用結(jié)束后,內(nèi)部的局部變量會(huì)被銷毀,但是由于counter()
內(nèi)部嵌套的count()
使用了nonlocal
來使用父函數(shù)的局部變量c
,所以c
是被重用了,即使外層函數(shù)調(diào)用結(jié)束了,c
并沒有被銷毀。
參考:
到此這篇關(guān)于Python嵌套函數(shù)與nonlocal使用詳細(xì)介紹的文章就介紹到這了,更多相關(guān)Python嵌套函數(shù)與nonlocal內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python數(shù)據(jù)預(yù)處理方式 :數(shù)據(jù)降維
今天小編就為大家分享一篇python數(shù)據(jù)預(yù)處理方式 :數(shù)據(jù)降維,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-02-02python tkinter實(shí)現(xiàn)彩球碰撞屏保
這篇文章主要為大家詳細(xì)介紹了python tkinter實(shí)現(xiàn)彩球碰撞屏保,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07Python內(nèi)存管理與泄漏排查實(shí)戰(zhàn)分享
這篇文章主要介紹了Python內(nèi)存管理與泄漏排查實(shí)戰(zhàn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-03-03Pandas之to_sql()插入數(shù)據(jù)到mysql中所遇到的問題及解決
這篇文章主要介紹了Pandas之to_sql()插入數(shù)據(jù)到mysql中所遇到的問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06