Python -- Python变量作用域

先看有有趣的问题

1
2
3
4
5
6
7
8
9
10
11
def f1(a):
    print (a)
    print (b)
f1(1)

Traceback (most recent call last):
  File "test.py", line 5, in <module>
    f1(1)
  File "test.py", line 3, in f1
    print (b)
NameError: global name 'b' is not defined

很明显是由于变量b未定义所以暴露出错误

修改一下

1
2
3
4
5
6
7
8
9
10
11
def f2(a):
    print (a)
    print (b)


b = 1
f2(1)

-----
1
1

很合理,如果先给b赋值再调用,这样就不会出现问题。

再修改一点点 – 有趣的例子

实现一个简单版本能够完成上文客户端调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
b = 3
def f3(a):
    print (a)
    print (b)
    b = 8

f3(1)

Traceback (most recent call last):
  File "test.py", line 9, in <module>
    f1(1)
  File "test.py", line 4, in f1
    print (b)
UnboundLocalError: local variable 'b' referenced before assignment
1
  • 首先输出了1 代表 print(a) 已经运行了。
  • 但是print(b)却报错了。
  • 我们看第二个例子,存在一个全局变量b 而且赋值是在输出之后进行的。

原因

Python编译函数的定义体时,它判断b是局部变量,因为在函数中给它赋值了。Python会尝试从本地环境获取b,但是尝试获取局部变量b的值时,发现b没有绑定值。

1
2
3
4
5
6
7
8
9
10
11
12
13
print (a)
  6           0 LOAD_FAST                0 (a)
              3 PRINT_ITEM          
              4 PRINT_NEWLINE       
print (b)  //从局部查询
  7           5 LOAD_FAST                1 (b)
              8 PRINT_ITEM          
              9 PRINT_NEWLINE       
b = 8
  8          10 LOAD_CONST               1 (8)
             13 STORE_FAST               1 (b)
             16 LOAD_CONST               0 (None)
             19 RETURN_VALUE   

我们再试试,不对b操作的情况

1
2
3
4
5
6
7
8
9
10
11
print (a)
  6           0 LOAD_FAST                0 (a)
              3 PRINT_ITEM          
              4 PRINT_NEWLINE       
print (b)  //从全局查询
  7           5 LOAD_GLOBAL              0 (b)
              8 PRINT_ITEM          
              9 PRINT_NEWLINE       
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE        

如此对比是不是就清楚明白了

记得操作全局变量要使用global关键字 ```python b = 1 def f4(a): global b print (a) print (b) b = 8

f4(1) ```

“世界就像是个巨大的马戏团,它让你兴奋,却让我惶恐,因为我知道散场后永远是有限温存,无限心酸。”