哪里出問題了
python 中,使用 global 會(huì)將全局變量設(shè)為本函數(shù)可用。同時(shí),在函數(shù)內(nèi)部訪問變量會(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() 中,沒有用 global,此時(shí)的b使用本地。所以 print 會(huì)打印本地 b
為什么會(huì)打印 12 ?還有 In[101]的 b 為 2 該怎么解釋?
y(),使用的 global 竟然沒把 x() 的 b = 12 導(dǎo)進(jìn)來。
在函數(shù) y() 中,語句 global a,b 使a,b擴(kuò)展為全局,所以,在最高層,就算沒有 b(In[98]),也會(huì)產(chǎn)生 b(In[101])。
也就是說, 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)in () ----> 1 b NameError: name 'b' is not defined
報(bào)錯(cuò)了! y() global b 后沒賦值,頂層就沒有 b。這說明,global 只是引入名稱,并不做賦值等操作。
global 不會(huì)管變量存不存在,只導(dǎo)入名稱,對(duì)該名稱的操作會(huì)反應(yīng)到 ‘最高層名稱空間‘。
再來:
In [109]: a = 111 In [110]: del b --------------------------------------------------------------------------- NameError Traceback (most recent call last)in () ----> 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) in () ----> 1 x() in x() 5 a = 1 6 print b ----> 7 y() 8 print "b =",b 9 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ù)傳遞問題
一、
首先,若只是取值,則不需要做任何處理。
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)in () ----> 1 x() in x() 5 a = 1 6 print "then a =",a ----> 7 y() 8 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)in () ----> 1 x() in x() a = 10 print("then a=",a) ----> 7 y() 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‘ 來描述就是:global 會(huì)將頂層變量名稱 綁定 到本地變量名稱,同時(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
沒有報(bào)錯(cuò),完美!
要注意 語句 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)in () ----> 1 x() in x() 5 print "msg =",msg 6 l = ["out msg"] ----> 7 y() 8 print l[0] 9 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ā)的一系列問題,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
