全局变量
定义一个函数,它读取两个变量的值:一个是局部变量a,是函数的参数,另一个是变量b,这个函数没有定义它
def f1(a):
print(a)
print(b)
print(f1(3))
# 运行结果
3
Traceback (most recent call last):
File "E:/virtual_workshop/everyday/test/f1.py", line 6, in <module>
print(f1(3))
File "E:/virtual_workshop/everyday/test/f1.py", line 3, in f1
print(b)
NameError: name 'b' is not defined
出现这样的错误并不奇怪,因为全局变量b并没有赋值,使用dis反汇编一下,可以看到是往栈里load了全局变量b
from dis import dis
print(dis(f1))
# 运行结果
2 0 LOAD_GLOBAL 0 (print)
2 LOAD_FAST 0 (a)
4 CALL_FUNCTION 1
6 POP_TOP
3 8 LOAD_GLOBAL 0 (print)
10 LOAD_GLOBAL 1 (b) #往栈里load了全局变量b
12 CALL_FUNCTION 1
14 POP_TOP
16 LOAD_CONST 0 (None)
18 RETURN_VALUE
None
怎么优化这个程序?只需要先给全局变量b赋值,然后再调用f
def f1(a):
print(a)
print(b)
b = 6
print(f1(3))
# 运行结果
3
6
None
局部变量
下面的f2函数,先给b赋值,然后再打印a和b的值
b = 6
def f2(a):
print(a)
print(b)
b = 9 #局部变量
print(f2(3))
# 运行结果
3
Traceback (most recent call last):
File "E:/virtual_workshop/everyday/test/f2.py", line 9, in <module>
print(f2(3))
File "E:/virtual_workshop/everyday/test/f2.py", line 6, in f2
print(b)
UnboundLocalError: local variable 'b' referenced before assignment
为什么会出现这样的情况呢,因为Python编译函数的时候,它判定b是局部变量,因为在函数中给它赋值了。生成的字节码正事了这种判断,Python会尝试从本地环境获取b。后面调用f2(3)时,f2的定义体会获取并打印局部变量a的值,但是尝试获取局部变量b的值时,发现b没有绑定值。这不是缺陷,而是设计选择:Python不要求声明变量,但是假定在函数体中赋值的变量是局部变量。使用dis反汇编一下,可以看到加载的b是局部变量
5 0 LOAD_GLOBAL 0 (print)
2 LOAD_FAST 0 (a)
4 CALL_FUNCTION 1
6 POP_TOP
6 8 LOAD_GLOBAL 0 (print)
10 LOAD_FAST 1 (b) #往栈里load了局部变量b
12 CALL_FUNCTION 1
14 POP_TOP
7 16 LOAD_CONST 1 (9)
18 STORE_FAST 1 (b)
20 LOAD_CONST 0 (None)
22 RETURN_VALUE
None
如果在函数中赋值时想让解释器把b当做全局变量,需要用global声明:
b = 6
def f2(a):
global b
print(a)
print(b)
b = 9 #局部变量
# 运行结果
3
6
None
参考书籍
《流畅的Python》