PYTHON 中使用 GLOBAL引发的一系列问题
哪里出问题了
python中,使用global会将全局变量设为本函数可用。同时,在函数内部访问变量会先本地再全局。
在嵌套函数中,使用global会产生不合常理的行为。
上代码:
In[96]:defx(): b=12 defy(): globala,b a=1 b=2 y() print"b=",b ....: In[97]:a=111 In[98]:delb In[99]:x() b=12 In[100]:a Out[100]:1 In[101]:b Out[101]:2
而在函数x()中,没有用global,此时的b使用本地。所以print会打印本地b
为什么会打印12?还有In[101]的b为2该怎么解释?
y(),使用的global竟然没把x()的b=12导进来。
在函数y()中,语句globala,b使a,b扩展为全局,所以,在最高层,就算没有b(In[98]),也会产生b(In[101])。
也就是说,globala,b,会认为a和b是最外层的变量。
再试一下:
In[102]:defx(): b=12 defy(): globala,b a=1 y() print"b=",b .....: In[103]:a=111 In[104]:delb In[105]:x() b=12 In[106]:a Out[106]:1 In[107]:b --------------------------------------------------------------------------- NameErrorTraceback(mostrecentcalllast) <ipython-input-107-3b5d5c371295>in<module>() ---->1b NameError:name'b'isnotdefined
报错了!y()globalb后没赋值,顶层就没有b。这说明,global只是引入名称,并不做赋值等操作。
global不会管变量存不存在,只导入名称,对该名称的操作会反应到‘最高层名称空间‘。
再来:
In[109]:a=111 In[110]:delb --------------------------------------------------------------------------- NameErrorTraceback(mostrecentcalllast) <ipython-input-110-745f2abe7045>in<module>() ---->1delb NameError:name'b'isnotdefined In[111]:defx(): b=12 defy(): globala,b a=1 printb y() print"b=",b .....: In[112]:x() --------------------------------------------------------------------------- NameErrorTraceback(mostrecentcalllast) <ipython-input-112-7354d77c61ac>in<module>() ---->1x() <ipython-input-111-c05fc67a1e82>inx() 5a=1 6printb ---->7y() 8print"b=",b 9 <ipython-input-111-c05fc67a1e82>iny() 4globala,b 5a=1 ---->6printb 7y() 8print"b=",b NameError:globalname'b'isnotdefined
这就确定了内层y()的global不会导入x()的东西。
那么,内层函数怎么使用正确的外层函数的变量呢?
解决内层函数参数传递问题
一、
首先,若只是取值,则不需要做任何处理。
In[119]:defx(): .....:a=12 .....:defy(): .....:printa .....:y() .....: In[120]:x() 12 In[121]:
在y()中,一旦为a赋值,a立马变内部变量。
In[121]:defx(): .....:a=12 .....:defy(): .....:print"beforea=",a .....:a=1 .....:print"thena=",a .....:y() .....: In[122]:x() beforea=--------------------------------------------------------------------------- UnboundLocalErrorTraceback(mostrecentcalllast) <ipython-input-122-7354d77c61ac>in<module>() ---->1x() <ipython-input-121-d8fbc0dba399>inx() 5a=1 6print"thena=",a ---->7y() 8 <ipython-input-121-d8fbc0dba399>iny() 2a=12 3defy(): ---->4print"beforea=",a 5a=1 6print"thena=",a UnboundLocalError:localvariable'a'referencedbeforeassignment
一旦在函数y()的某处给a赋值,则在赋值前,python会认为a不存在。
同时发现python2的print会一个一个的输出。鉴于此,我又在python3中试了,发现他是一起输出。但这不是本文重点,折叠之。
In[7]:defx(): a=1 defy(): print("beforea=",a) a=10 print("thena=",a) y() ...: In[8]:x() --------------------------------------------------------------------------- UnboundLocalErrorTraceback(mostrecentcalllast) <ipython-input-8-7354d77c61ac>in<module>() ---->1x() <ipython-input-7-6e01e7317b24>inx() a=10 print("thena=",a) ---->7y() <ipython-input-7-6e01e7317b24>iny() a=1 defy(): ---->4print("beforea=",a) a=10 print("thena=",a) UnboundLocalError:localvariable'a'referencedbeforeassignment
同时发现python代码运行前会先扫一遍代码的,而不是单纯的一行一行的执行。
同时发现返回UnboundLocalError,而不是NameError。注意到'unbound‘,这是官方概念。用'unbound‘来描述就是:global会将顶层变量名称绑定到本地变量名称,同时变化,是为'引用‘;python检测到a=1时,意识到a是本地的,所以在a'指向一个对象‘(因为python变量均为引用),之前,调用a是非法行为,但这种行为区别于于NameError,就定义为unboundlocal。
二、
使用可变变量,如list,dict
In[127]:defx(): .....:l=["inmsg"] .....:defy(): .....:msg=l[0] .....:print"msg=",msg .....:l[:]=["outmsg"] .....:y() .....:printl[0] .....: In[128]:x() msg=inmsg outmsg
没有报错,完美!
要注意语句l[:]=["outmsg"],使用切片赋值,否则,
In[129]:defx(): l=["inmsg"] defy(): msg=l[0] print"msg=",msg l=["outmsg"] y() printl[0] .....: In[130]:x() --------------------------------------------------------------------------- UnboundLocalErrorTraceback(mostrecentcalllast) <ipython-input-130-7354d77c61ac>in<module>() ---->1x() <ipython-input-129-d44e750e285f>inx() 5print"msg=",msg 6l=["outmsg"] ---->7y() 8printl[0] 9 <ipython-input-129-d44e750e285f>iny() 2l=["inmsg"] 3defy(): ---->4msg=l[0] 5print"msg=",msg 6l=["outmsg"] UnboundLocalError:localvariable'l'referencedbeforeassignment
又出UnboundLocalError了,因为第六行代码为l分配了一个新的list。
三、
利用参数传递。
In[136]:defx(): .....:a,b=1,2 .....:defy(a=a,b=b): .....:a,b=3,4 .....:returna,b .....:a,b=y() .....:printa,b .....: In[137]:x() 34
注意,不要在默认参数上放list等可变对象。
以上所述是小编给大家介绍的PYTHON中使用GLOBAL引发的一系列问题,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!