哪里出问题了
python 中,使用 global 会将全局变量设为本函数可用。同时,在函数内部访问变量会先本地再全局。
在嵌套函数中,使用 global 会产生不合常理的行为。
上代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
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 是最外层的变量。
再试一下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
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 |
报错了! y() global b 后没赋值,顶层就没有 b。这说明,global 只是引入名称,并不做赋值等操作。
global 不会管变量存不存在,只导入名称,对该名称的操作会反应到 ‘最高层名称空间‘。
再来:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
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 |
这就确定了 内层y() 的 global 不会 导入 x() 的东西。
那么,内层函数怎么使用正确的外层函数的变量呢?
解决内层函数参数传递问题
一、
首先,若只是取值,则不需要做任何处理。
1
2
3
4
5
6
7
8
9
|
In [ 119 ]: def x(): .....: a = 12 .....: def y(): .....: print a .....: y() .....: In [ 120 ]: x() 12 In [ 121 ]: |
在 y() 中,一旦为 a 赋值,a 立马变内部变量。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
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 |
一旦在函数 y() 的某处给 a 赋值,则在赋值前,python 会认为 a 不存在。
同时发现 python2 的 print 会一个一个的 输出。鉴于此,我又在 python3 中试了,发现他是 一起输出。但这不是本文重点,折叠之。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
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 |
同时发现 python代码运行前 会先扫一遍代码的,而不是单纯的一行一行的执行。
同时发现返回 UnboundLocalError,而不是 NameError。注意到 'unbound‘,这是官方概念。用 'unbound‘ 来描述就是:global 会将顶层变量名称 绑定 到本地变量名称,同时变化,是为 '引用‘;python 检测到 a = 1时,意识到 a 是本地的,所以 在 a '指向一个对象‘(因为python变量均为引用),之前 ,调用 a 是非法 行为,但这种行为区别于于 NameError,就定义为 unbound local。
二、
使用 可变变量,如 list,dict
1
2
3
4
5
6
7
8
9
10
11
12
|
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"] ,使用切片赋值,否则,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
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 了,因为 第六行代码 为 l 分配了 一个新的 list。
三、
利用参数传递。
1
2
3
4
5
6
7
8
9
10
|
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引发的一系列问题,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对服务器之家网站的支持!