1 函數(shù)嵌套
創(chuàng)新互聯(lián)公司堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的濮陽(yáng)縣網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!一個(gè)函數(shù)中存在另外一個(gè)函數(shù)(定義/調(diào)用),這種方式我們稱(chēng)之為函數(shù)嵌套。所以:函數(shù)的嵌套主要分為嵌套調(diào)用,以及嵌套定義。
注意:在函數(shù)的內(nèi)部定義函數(shù),只能在函數(shù)內(nèi)部進(jìn)行調(diào)用,在其他地方是無(wú)法進(jìn)行調(diào)用,強(qiáng)行調(diào)用就會(huì)提示NameError異常,所以說(shuō)函數(shù)是有可見(jiàn)范圍的,這就涉及到了作用域了
2 作用域
一個(gè)標(biāo)識(shí)符的可見(jiàn)范圍,叫做標(biāo)識(shí)符的作用域。一般常說(shuō)的是變量的作用域。根據(jù)作用的范圍主要分為全局作用域和局部作用域。
全局作用域:在整個(gè)程序運(yùn)行環(huán)境中都可見(jiàn)
局部作用域:在函數(shù)、類(lèi)的內(nèi)部可見(jiàn),并且使用范圍不能超過(guò)所在的局部作用域(比如在函數(shù)內(nèi)部定義了一個(gè)變量x,我在全局使用變量x是不行的。)
全局變量x在全局生效,所以內(nèi)部函數(shù)inner是可以打印x的
局部變量y只在inner內(nèi)部生效,所以在全局print(y) 是無(wú)法調(diào)用局部變量y的
觀察下面的例子:
代碼是從上到下執(zhí)行的,所欲這樣寫(xiě)也沒(méi)什么毛病,但是這里這個(gè)例子是無(wú)法執(zhí)行的,為什么呢?
x作為全局變量,在inner內(nèi)部是可見(jiàn)的
在定義函數(shù)的階段,Python的函數(shù)是作為一個(gè)整體一起被解釋的。
inner函數(shù)在解釋時(shí),解釋器發(fā)現(xiàn)在inner內(nèi)部對(duì)x進(jìn)行了定義(x += 1),那么它就不會(huì)在調(diào)用全局變量x,而是標(biāo)識(shí)x是局部定義的變量
而在執(zhí)行x+=1的時(shí)候,inner內(nèi)部的x還沒(méi)有被定義,所以會(huì)提示x在定義前被執(zhí)行了。(x += 1 --> x = x + 1 ,預(yù)先求 x + 1 時(shí)提示的)。
如何解決呢?有兩種方法:更換變量名稱(chēng)、聲明當(dāng)前變量非本地變量(global)
2.1 global關(guān)鍵字
我們通過(guò)在函數(shù)內(nèi)部使用global關(guān)鍵字來(lái)聲明一個(gè)變量不是局部變量,而是一個(gè)全局變量。
雖然全局變量x,在全局沒(méi)有被定義,但是由于在函數(shù)內(nèi)部使用了global關(guān)鍵字,所以x就變成了全局變量了。使用了global關(guān)鍵字,那么之前的例子就可以進(jìn)行如下修改了
針對(duì)global的總結(jié):
外部作用域變量在內(nèi)部作用域是可見(jiàn)的,但是不要在內(nèi)部函數(shù)中直接使用或者修改,因?yàn)楹瘮?shù)的目的就是為了封裝,盡量與外界隔離。
如果函數(shù)需要使用外部全局變量,請(qǐng)盡量使用函數(shù)的形參定義,在調(diào)用時(shí)傳遞實(shí)參來(lái)使用
建議不要使用global。
3 閉包
在很多編程語(yǔ)言中都存在閉包的概念,那什么是閉包呢?閉包其實(shí)就是一個(gè)概念,出現(xiàn)在嵌套函數(shù)中,指的是:內(nèi)層函數(shù)引用到了外層函數(shù)的自由變量,就形成了閉包
自由變量:未在本地作用域中定義的變量,比如在嵌套函數(shù)的外層定義的變量(非全局變量),對(duì)內(nèi)層來(lái)說(shuō),這個(gè)變量就叫做自由變量。
注意:上面這個(gè)例子比較特殊,首先它是一個(gè)閉包,在inner函數(shù)內(nèi)引用了外層函數(shù)的自由變量C。因?yàn)檫@里的c是一個(gè)引用類(lèi)型,我們可以直接通過(guò)c來(lái)操作c中的元素,但是沒(méi)辦法對(duì)c本身進(jìn)行修改,即c += [1,3]??此剖橇斜砥唇樱撬鼤?huì)重新對(duì)c進(jìn)行聲明,這就引發(fā)了之前的問(wèn)題,內(nèi)部函數(shù)inner沒(méi)有定義c,所以會(huì)報(bào)錯(cuò)!所以當(dāng)c不是引用類(lèi)型的話,我們就沒(méi)辦法修改了嗎?當(dāng)然不是,可以使用global把c聲明為全局變量,但是這就不是閉包了,所以這里就需要使用nonlocal了(python 3 特有)。
疑問(wèn)?我們都說(shuō)函數(shù)執(zhí)行完畢后,函數(shù)的內(nèi)部變量將會(huì)被回收,這里的outer執(zhí)行完畢后,那么變量c應(yīng)該會(huì)被回收啊,為什么還能被內(nèi)層的inner找到呢?這是因?yàn)樵诙x階段,解釋器解釋到inner函數(shù)時(shí),由于函數(shù)是作為一個(gè)整體被解析的,所以解釋器知道在inner內(nèi)部引用了外部的變量,所以在執(zhí)行函數(shù)outer時(shí),并不會(huì)回收已被內(nèi)部函數(shù)inner引用的自由變量c。
3.1 nonlocal關(guān)鍵字
使用了nonlocal關(guān)鍵字,將變量標(biāo)記為不在本地作用域定義,而在上一級(jí)局部作用域中定義,但不能是全局作用域中定義。
nonlocal只能用在嵌套函數(shù)的內(nèi)部
4 默認(rèn)值的作用域
在Python中,一切皆對(duì)象,函數(shù)也不列外,當(dāng)我們給函數(shù)定義默認(rèn)值時(shí),Python會(huì)把它存放在函數(shù)的屬性中,這個(gè)屬性值就伴隨這個(gè)函數(shù)對(duì)象的整個(gè)生命周期。
foo.__defaults__屬性查看函數(shù)的默認(rèn)值屬性
仔細(xì)查看輸出結(jié)果,發(fā)現(xiàn)函數(shù)地址沒(méi)有變,也就是說(shuō)函數(shù)這個(gè)對(duì)象沒(méi)有變,但是我們發(fā)現(xiàn)每次它的__default__屬性都會(huì)發(fā)生變化,這是為什么呢?這是因?yàn)閟ed和list的默認(rèn)值都是引用類(lèi)型,它們引用的都是函數(shù)在定義時(shí)定義的默認(rèn)值中。 雖然函數(shù)執(zhí)行完就釋放了內(nèi)存空間,也是由于引用類(lèi)型,指向默認(rèn)空間的指針沒(méi)了,但是已經(jīng)在調(diào)用時(shí)改變了默認(rèn)值空間的對(duì)象中的元素,所以在下一次再次調(diào)用時(shí)此時(shí)默認(rèn)值空間的元素已經(jīng)被改變了。所以當(dāng)函數(shù)的默認(rèn)值為引用類(lèi)型時(shí),這點(diǎn)要特別的注意了
解決辦法:
在定義時(shí)使用引用類(lèi)型時(shí),在函數(shù)內(nèi)部使用前先進(jìn)行copy。
在定義函數(shù)時(shí)默認(rèn)使用None值,在函數(shù)內(nèi)判斷如果是None則開(kāi)辟一個(gè)引用類(lèi)型。
5 變量名解析原則LEGB
變量的解析原則,也可以理解為變量的查找順序:
L(Local): 本地作用域、局部作用域的local命名空間。函數(shù)調(diào)用是創(chuàng)建,調(diào)用結(jié)束消亡
E(Enclosing): Python 2.2時(shí)引入嵌套函數(shù),實(shí)現(xiàn)了閉包,這個(gè)就是嵌套函數(shù)的外部函數(shù)的命名空間
G(Global): 全局作用域,即一個(gè)模塊的命名空間。模塊被import時(shí)創(chuàng)建,解釋器退出時(shí)消亡
B(Build-in): 內(nèi)置模塊的命名空間,生命周期從Python解釋器啟動(dòng)時(shí)創(chuàng)建到解釋器退出時(shí)消亡。例如print函數(shù)、open函數(shù)等。
變量查找的規(guī)則為 L > E > G > B,即:先本地后嵌套再全局最后是內(nèi)置函數(shù)中
6 函數(shù)的銷(xiāo)毀
全局函數(shù):
重新定義同名函數(shù)
del 語(yǔ)句刪除函數(shù)名稱(chēng),函數(shù)對(duì)象引用計(jì)數(shù)減1
程序結(jié)束時(shí)
局部函數(shù):
重新在上級(jí)作用域定義同名函數(shù)
del 語(yǔ)句刪除函數(shù)名稱(chēng),函數(shù)對(duì)象的引用計(jì)數(shù)減1
上級(jí)作用域銷(xiāo)毀時(shí)
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)cdcxhl.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專(zhuān)為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。
標(biāo)題名稱(chēng):Python函數(shù)嵌套-作用域-閉包-LEGB-函數(shù)銷(xiāo)毀-創(chuàng)新互聯(lián)
URL地址:http://www.rwnh.cn/article48/cspoep.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站制作、微信公眾號(hào)、企業(yè)建站、面包屑導(dǎo)航、網(wǎng)站策劃、建站公司
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容