如果Python一次执行一行,为什么它们在声明之前就能看到变量?

tem*_*ame 4 python scope compilation python-3.x

x = 4
def test():
    print(x)
    x = 2
test()
Run Code Online (Sandbox Code Playgroud)

这会产生错误,因为当你去的时候print(x),它会看到你x在函数的范围内声明了test它,并且它告诉你你在没有声明的情况下尝试引用它.

我知道,如果我这样做global x没有问题,或者如果我移动打印声明......我知道.

但是我不明白解释器是如何知道我x在print语句之后重新声明的,如果它一次通过代码一行.怎么知道会发生什么?

显然,这比我所知道的要多得多.

aba*_*ert 7

谁告诉你Python一次执行一行?Python一次执行一个字节码.该字节码来自编译器,它一次只能运行一个语句.语句可以是多行.函数定义是一个声明.

因此,编译函数定义的第一步是收集在该函数体内分配的所有变量.已分配但没有globalnonlocal声明的任何变量都是本地变量.

(作为旁注,该函数体实际上并没有被编译成函数,它被编译成一个code对象,它被隐藏在某个地方,只在你调用函数时运行,并进入一些字节码,function从该code对象构建一个对象,以正常顺序发生函数定义时运行.)

实际上,您可以通过查看其成员来查看编译器对您的函数所做的操作:

>>> def foo():
...     global y
...     x=1
...     y=1
>>> foo.__code__.co_varnames
('x',)
Run Code Online (Sandbox Code Playgroud)

然后,当它为您的函数体创建字节码时,所有变量co_varnames都被编译为本地查找,而其余变量则被编译为全局查找:

>>> dis.dis(foo)
  3           0 LOAD_CONST               1 (1)
              3 STORE_FAST               0 (x)

  4           6 LOAD_CONST               1 (1)
              9 STORE_GLOBAL             0 (y)
             12 LOAD_CONST               0 (None)
             15 RETURN_VALUE        
Run Code Online (Sandbox Code Playgroud)