python - 为什么对全局变量的错误分配会提早引发异常?

标签 python function python-3.x scope

a = 10
def f():
  print(1)
  print(a) # UnboundLocalError raised here
  a = 20
f()

这段代码当然会引发 UnboundLocalError: local variable 'a' referenced before assignment。但是为什么会在 print(a) 行引发此异常?

如果解释器逐行执行代码(就像我想的那样),当到达 print(a) 时它不会知道有什么错误;它只会认为 a 引用了全局变量。

所以解释器似乎提前读取了整个函数,以确定是否使用 a 进行赋值。这在任何地方都有记录吗?有没有其他解释器向前看的情况(除了检查语法错误)?

澄清一下,异常本身是非常清楚的:全局变量可以在没有 global 声明的情况下读取,但不能写入(这种设计可以防止由于无意中修改全局变量而导致的错误;这些错误特别难以解决调试,因为它们会导致错误发生在远离错误代码位置的地方)。我只是好奇为什么提早提出异常。

最佳答案

根据 Python's documentation ,解释器将首先注意到在 f() 范围内对名为 a 的变量的赋值(无论赋值在函数中的位置如何),然后作为 a结果仅将变量 a 识别为该范围内的局部变量。此行为有效 shadows全局变量a

异常随后“提早”引发,因为“逐行”执行代码的解释器将遇到引用局部变量的打印语句,此时该变量尚未绑定(bind)(记住,Python 正在寻找一个 local 变量)。

正如您在问题中提到的,必须使用 global 关键字明确告诉编译器此范围内的赋值是对全局变量完成的,正确的代码是:

a = 10
def f():
  global a
  print(1)
  print(a) # Prints 10 as expected
  a = 20
f()

作为@2rs2ts在现已删除的答案中说,这很容易解释为“Python 不仅仅是被解释,它被编译成字节码,而不仅仅是逐行解释”。

关于python - 为什么对全局变量的错误分配会提早引发异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40822067/

相关文章:

python - 这些奇特的 TypeVar 的 PyCharm 生成了什么?

javascript - 如何通过jQuery的点击函数获取用户输入

list - Haskell 是否有用于创建将函数应用于列表的每个变体的函数

c++ - C/C++ 函数中的 LoadLibrary 和 GetProcAddress

python - 设置另一个程序总是在最前面?

python - 如果值超过 matplotlib 中的 xlim,如何环绕绘图

Python - 将文件移动到包含部分文件名的文件夹

python - 日期比较/连续日期分组

python - JSON 加载返回 unicode 而不是字典

python - 基方法和子方法签名中的参数数量不一致