PYTHON 中使用 GLOBAL引發(fā)的一系列問(wèn)題
哪里出問(wèn)題了
python 中,使用 global 會(huì)將全局變量設(shè)為本函數(shù)可用。同時(shí),在函數(shù)內(nèi)部訪(fǎng)問(wèn)變量會(huì)先本地再全局。
在嵌套函數(shù)中,使用 global 會(huì)產(chǎn)生不合常理的行為。
上代碼:
In [96]: def x(): b = 12 def y(): global a,b a = 1 b = 2 y() print "b =",b ....: In [97]: a = 111 In [98]: del b In [99]: x() b = 12 In [100]: a Out[100]: 1 In [101]: b Out[101]: 2
而在函數(shù) x() 中,沒(méi)有用 global,此時(shí)的b使用本地。所以 print 會(huì)打印本地 b
為什么會(huì)打印 12 ?還有 In[101]的 b 為 2 該怎么解釋?
y(),使用的 global 竟然沒(méi)把 x() 的 b = 12 導(dǎo)進(jìn)來(lái)。
在函數(shù) y() 中,語(yǔ)句 global a,b 使a,b擴(kuò)展為全局,所以,在最高層,就算沒(méi)有 b(In[98]),也會(huì)產(chǎn)生 b(In[101])。
也就是說(shuō), global a,b ,會(huì)認(rèn)為 a 和 b 是最外層的變量。
再試一下:
In [102]: def x(): b = 12 def y(): global a,b a = 1 y() print "b =",b .....: In [103]: a = 111 In [104]: del b In [105]: x() b = 12 In [106]: a Out[106]: 1 In [107]: b --------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-107-3b5d5c371295> in <module>() ----> 1 b NameError: name 'b' is not defined
報(bào)錯(cuò)了! y() global b 后沒(méi)賦值,頂層就沒(méi)有 b。這說(shuō)明,global 只是引入名稱(chēng),并不做賦值等操作。
global 不會(huì)管變量存不存在,只導(dǎo)入名稱(chēng),對(duì)該名稱(chēng)的操作會(huì)反應(yīng)到 ‘最高層名稱(chēng)空間‘。
再來(lái):
In [109]: a = 111 In [110]: del b --------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-110-745f2abe7045> in <module>() ----> 1 del b NameError: name 'b' is not defined In [111]: def x(): b = 12 def y(): global a,b a = 1 print b y() print "b =",b .....: In [112]: x() --------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-112-7354d77c61ac> in <module>() ----> 1 x() <ipython-input-111-c05fc67a1e82> in x() 5 a = 1 6 print b ----> 7 y() 8 print "b =",b 9 <ipython-input-111-c05fc67a1e82> in y() 4 global a,b 5 a = 1 ----> 6 print b 7 y() 8 print "b =",b NameError: global name 'b' is not defined
這就確定了 內(nèi)層y() 的 global 不會(huì) 導(dǎo)入 x() 的東西。
那么,內(nèi)層函數(shù)怎么使用正確的外層函數(shù)的變量呢?
解決內(nèi)層函數(shù)參數(shù)傳遞問(wèn)題
一、
首先,若只是取值,則不需要做任何處理。
In [119]: def x(): .....: a = 12 .....: def y(): .....: print a .....: y() .....: In [120]: x() 12 In [121]:
在 y() 中,一旦為 a 賦值,a 立馬變內(nèi)部變量。
In [121]: def x(): .....: a = 12 .....: def y(): .....: print "before a =",a .....: a = 1 .....: print "then a =",a .....: y() .....: In [122]: x() before a =--------------------------------------------------------------------------- UnboundLocalError Traceback (most recent call last) <ipython-input-122-7354d77c61ac> in <module>() ----> 1 x() <ipython-input-121-d8fbc0dba399> in x() 5 a = 1 6 print "then a =",a ----> 7 y() 8 <ipython-input-121-d8fbc0dba399> in y() 2 a = 12 3 def y(): ----> 4 print "before a =",a 5 a = 1 6 print "then a =",a UnboundLocalError: local variable 'a' referenced before assignment
一旦在函數(shù) y() 的某處給 a 賦值,則在賦值前,python 會(huì)認(rèn)為 a 不存在。
同時(shí)發(fā)現(xiàn) python2 的 print 會(huì)一個(gè)一個(gè)的 輸出。鑒于此,我又在 python3 中試了,發(fā)現(xiàn)他是 一起輸出。但這不是本文重點(diǎn),折疊之。
In [7]: def x(): a = 1 def y(): print("before a=",a) a = 10 print("then a=",a) y() ...: In [8]: x() --------------------------------------------------------------------------- UnboundLocalError Traceback (most recent call last) <ipython-input-8-7354d77c61ac> in <module>() ----> 1 x() <ipython-input-7-6e01e7317b24> in x() a = 10 print("then a=",a) ----> 7 y() <ipython-input-7-6e01e7317b24> in y() a = 1 def y(): ----> 4 print("before a=",a) a = 10 print("then a=",a) UnboundLocalError: local variable 'a' referenced before assignment
同時(shí)發(fā)現(xiàn) python代碼運(yùn)行前 會(huì)先掃一遍代碼的,而不是單純的一行一行的執(zhí)行。
同時(shí)發(fā)現(xiàn)返回 UnboundLocalError,而不是 NameError。注意到 'unbound‘,這是官方概念。用 'unbound‘ 來(lái)描述就是:global 會(huì)將頂層變量名稱(chēng) 綁定 到本地變量名稱(chēng),同時(shí)變化,是為 '引用‘;python 檢測(cè)到 a = 1時(shí),意識(shí)到 a 是本地的,所以 在 a '指向一個(gè)對(duì)象‘(因?yàn)閜ython變量均為引用),之前 ,調(diào)用 a 是非法 行為,但這種行為區(qū)別于于 NameError,就定義為 unbound local。
二、
使用 可變變量,如 list,dict
In [127]: def x(): .....: l = ["in msg"] .....: def y(): .....: msg = l[0] .....: print "msg =",msg .....: l[:] = ["out msg"] .....: y() .....: print l[0] .....: In [128]: x() msg = in msg out msg
沒(méi)有報(bào)錯(cuò),完美!
要注意 語(yǔ)句 l[:] = ["out msg"] ,使用切片賦值,否則,
In [129]: def x(): l = ["in msg"] def y(): msg = l[0] print "msg =",msg l = ["out msg"] y() print l[0] .....: In [130]: x() --------------------------------------------------------------------------- UnboundLocalError Traceback (most recent call last) <ipython-input-130-7354d77c61ac> in <module>() ----> 1 x() <ipython-input-129-d44e750e285f> in x() 5 print "msg =",msg 6 l = ["out msg"] ----> 7 y() 8 print l[0] 9 <ipython-input-129-d44e750e285f> in y() 2 l = ["in msg"] 3 def y(): ----> 4 msg = l[0] 5 print "msg =",msg 6 l = ["out msg"] UnboundLocalError: local variable 'l' referenced before assignment
又出 UnboundLocalError 了,因?yàn)?第六行代碼 為 l 分配了 一個(gè)新的 list。
三、
利用參數(shù)傳遞。
In [136]: def x(): .....: a, b = 1, 2 .....: def y(a = a, b = b): .....: a, b = 3, 4 .....: return a, b .....: a, b = y() .....: print a, b .....: In [137]: x() 3 4
注意,不要在默認(rèn)參數(shù)上放 list等可變對(duì)象。
以上所述是小編給大家介紹的PYTHON 中使用 GLOBAL引發(fā)的一系列問(wèn)題,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
用pickle存儲(chǔ)Python的原生對(duì)象方法
下面小編就為大家?guī)?lái)一篇用pickle存儲(chǔ)Python的原生對(duì)象方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04Django數(shù)據(jù)庫(kù)連接丟失問(wèn)題的解決方法
這篇文章主要介紹了Django數(shù)據(jù)庫(kù)連接丟失問(wèn)題的解決方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-12-12python實(shí)戰(zhàn)小游戲之考驗(yàn)記憶力
本篇文章介紹了用python編寫(xiě)的曾經(jīng)風(fēng)靡的考驗(yàn)記憶力的小游戲,詳細(xì)介紹了整個(gè)思路和過(guò)程以及代碼,通讀本篇對(duì)大家的學(xué)習(xí)或工作具有一定的價(jià)值,需要的朋友可以參考下2021-09-09Python實(shí)現(xiàn)計(jì)算字符串中出現(xiàn)次數(shù)最多的字符示例
這篇文章主要介紹了Python實(shí)現(xiàn)計(jì)算字符串中出現(xiàn)次數(shù)最多的字符,涉及Python針對(duì)字符串的遍歷、統(tǒng)計(jì)等相關(guān)操作技巧,需要的朋友可以參考下2019-01-01numpy中實(shí)現(xiàn)ndarray數(shù)組返回符合特定條件的索引方法
下面小編就為大家分享一篇numpy中實(shí)現(xiàn)ndarray數(shù)組返回符合特定條件的索引方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-04-04python利用faker庫(kù)批量生成測(cè)試數(shù)據(jù)
小編經(jīng)常需要批量測(cè)試一些數(shù)據(jù),有時(shí)候測(cè)試環(huán)境又暫時(shí)沒(méi)數(shù)據(jù),特意找了一下,發(fā)現(xiàn)有一個(gè)可批量生成數(shù)據(jù)的python庫(kù)—-faker,現(xiàn)在就介紹一下它的使用方法,如果你不想一行一行輸入代碼,小編提供了完整測(cè)試代碼,見(jiàn)文末代碼章節(jié)。2020-10-10圖文講解選擇排序算法的原理及在Python中的實(shí)現(xiàn)
這篇文章主要介紹了選擇排序的原理及在Python中的實(shí)現(xiàn),選擇排序的時(shí)間復(fù)雜度為О(n²),需要的朋友可以參考下2016-05-05pytest用yaml文件編寫(xiě)測(cè)試用例流程詳解
這篇文章主要介紹了pytest用yaml文件編寫(xiě)測(cè)試用例流程,本文通過(guò)實(shí)例代碼圖文相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-12-12