哪里出问题了

python 中,使用 global 会将全局变量设为本函数可用。同时,在函数内部访问变量会先本地再全局。

在嵌套函数中,使用 global 会产生不合常理的行为。

上代码:

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

而在函数 x() 中,没有用 global,此时的b使用本地。所以 print 会打印本地 b

为什么会打印 12 ?还有 In[101]的 b 为 2 该怎么解释?

y(),使用的 global 竟然没把 x() 的 b = 12 导进来。

在函数 y() 中,语句 global a,b 使a,b扩展为全局,所以,在最高层,就算没有 b(In[98]),也会产生 b(In[101])。

也就是说, global a,b ,会认为 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

报错了! y() global b 后没赋值,顶层就没有 b。这说明,global 只是引入名称,并不做赋值等操作。

global 不会管变量存不存在,只导入名称,对该名称的操作会反应到 ‘最高层名称空间‘。

再来:

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

这就确定了 内层y() 的 global 不会 导入 x() 的东西。

那么,内层函数怎么使用正确的外层函数的变量呢?

解决内层函数参数传递问题

一、

首先,若只是取值,则不需要做任何处理。

In [119]:def x():
.....: a= 12
.....:def y():
.....:print a
.....: y()
.....:
In [120]: x()
12
In [121]:

在 y() 中,一旦为 a 赋值,a 立马变内部变量。

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

一旦在函数 y() 的某处给 a 赋值,则在赋值前,python 会认为 a 不存在。

同时发现 python2 的 print 会一个一个的 输出。鉴于此,我又在 python3 中试了,发现他是 一起输出。但这不是本文重点,折叠之。

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

同时发现 python代码运行前 会先扫一遍代码的,而不是单纯的一行一行的执行。

同时发现返回 UnboundLocalError,而不是 NameError。注意到 'unbound‘,这是官方概念。用 'unbound‘ 来描述就是:global 会将顶层变量名称 绑定 到本地变量名称,同时变化,是为 '引用‘;python 检测到 a = 1时,意识到 a 是本地的,所以 在 a '指向一个对象‘(因为python变量均为引用),之前 ,调用 a 是非法 行为,但这种行为区别于于 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

没有报错,完美!

要注意 语句 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 了,因为 第六行代码 为 l 分配了 一个新的 list。

三、

利用参数传递。

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

注意,不要在默认参数上放 list等可变对象。

以上所述是小编给大家介绍的PYTHON 中使用 GLOBAL引发的一系列问题,希望对大家有所帮助