我理解Python中局部变量和全局变量的概念,但我只是问一下为什么错误会出现在下面的代码中。 Python逐行执行代码,因此在读取第5行之前,它不知道a是局部变量。在尝试执行第5行后,Python是否会返回一行并将其标记为错误?
a=0
def test():
print a #line 4, Error : local variable 'a' referenced before assignment
a=0 #line 5
test()
答案 0 :(得分:12)
设置和测试
要分析您的问题,让我们创建两个独立的测试函数来复制您的问题:
a=0
def test1():
print(a)
test1()
打印0
。因此,调用此函数不是问题,而是在下一个函数上:
def test2():
print(a) # Error : local variable 'a' referenced before assignment
a=0
test2()
我们收到错误:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in test2
UnboundLocalError: local variable 'a' referenced before assignment
<强>拆卸强>
我们可以反汇编这两个函数(第一个 Python 2 ):
>>> import dis
>>> dis.dis(test1)
2 0 LOAD_GLOBAL 0 (a)
3 PRINT_ITEM
4 PRINT_NEWLINE
5 LOAD_CONST 0 (None)
8 RETURN_VALUE
我们看到第一个函数自动加载全局a
,而第二个函数:
>>> dis.dis(test2)
2 0 LOAD_FAST 0 (a)
3 PRINT_ITEM
4 PRINT_NEWLINE
3 5 LOAD_CONST 1 (0)
8 STORE_FAST 0 (a)
11 LOAD_CONST 0 (None)
14 RETURN_VALUE
看到在其中分配a
,尝试从本地进行LOAD_FAST(作为优化,因为函数在运行之前被预编译为字节代码。)
如果我们在 Python 3 中运行它,我们会看到几乎相同的效果:
>>> test2()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in test2
UnboundLocalError: local variable 'a' referenced before assignment
>>>
>>> import dis
>>> dis.dis(test1)
2 0 LOAD_GLOBAL 0 (print)
3 LOAD_GLOBAL 1 (a)
6 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
9 POP_TOP
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
>>> dis.dis() # disassembles the last stack trace
2 0 LOAD_GLOBAL 0 (print)
--> 3 LOAD_FAST 0 (a)
6 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
9 POP_TOP
3 10 LOAD_CONST 1 (0)
13 STORE_FAST 0 (a)
16 LOAD_CONST 0 (None)
19 RETURN_VALUE
我们再次看到错误在LOAD_FAST上。
答案 1 :(得分:6)
Python不会在您提交的功能代码中逐行执行。它首先将其解析为执行块。它决定变量是局部变量还是全局变量,具体取决于它是否写入(函数)本地级别。在这种情况下,它决定变量是本地的,因此是错误。
答案 2 :(得分:4)
这是因为,在python中,您需要告诉您要修改全局变量的值。你那样做:
def test():
global a
print a #line 4, Error : local variable 'a' referenced before assignment
a=0 #line 5
使用global a
,您可以修改函数中的变量。
你可能想看看这个:
答案 3 :(得分:3)
简短说明:
a
变量绑定到test
函数。当您尝试打印它时,Python会抛出错误,因为稍后将初始化本地变量a
。但是如果删除a=0
,代码将毫无问题地执行并输出0。
更长的解释
Python解释器开始从本地范围搜索名为a
的变量。它看到a
确实在函数中声明并且仅在第五行初始化。一旦找到,查找就结束了。
当它试图处理print a
(第四行)时,它说'哦,男孩,我需要打印一个尚未初始化的变量,我最好抛出一个错误。&#39;
基于功能的字节码
的说明如果您运行此代码:
import dis
a = 0
def test():
print a #line 4, Error : local variable 'a' referenced before assignment
a = 0 #line 5
dis.dis(test)
您将获得此输出:
6 0 LOAD_FAST 0 (a)
3 PRINT_ITEM
4 PRINT_NEWLINE
7 5 LOAD_CONST 1 (0)
8 STORE_FAST 0 (a)
11 LOAD_CONST 0 (None)
14 RETURN_VALUE
对上述不清楚部分的解释:
a
的引用被推入堆栈。a
所以,问题是LOAD_FAST在STORE_FAST之前。