x = 1infunc2 不是自由变量。这只是另一个本地人;默认情况下,您绑定到的名称和绑定的名称是本地人,除非您另外告诉 Python。
来自相同的执行模型文档:
如果名称绑定在块中,则它是该块的局部变量,除非声明为nonlocalor global。[...] 如果变量在代码块中使用但未在其中定义,则它是自由变量。
(粗体强调我的)
您用 绑定了块中的名称x = 1,因此它是该块中的局部变量,不能是自由变量。所以你发现的部分不适用,因为那只适用于自由变量:
如果自由变量的最近封闭范围包含global语句,则自由变量被视为全局变量。
您不应该绑定xin func2(),因为只有在范围内未绑定的名称才是自由变量。
所以这有效:
>>> def func1():
... global x
... x = 1
... def func2():
... print(x) # x is a free variable here
... func2()
...
>>> func1()
1
>>> x
1
xinfunc2现在是一个自由变量;它未在 的范围内定义func2,因此从父范围中获取。这里的父作用域是func1,但x在那里被标记为全局,因此在读取 x函数时使用print()全局值。
x将此与未标记为全局 in 进行对比func1:
>>> def func1():
... x = 1
... def func2():
... print(x) # x is free variable here, now referring to x in func1
... func2()
...
>>> x = 42
>>> func1()
1
这里全局名称x设置为42,但这不会影响打印的内容。xinfunc2是一个自由变量,但父范围func1仅x作为本地名称。
当您添加一个仍然是本地的新最外层范围时,它变得更加有趣:x
>>> def outerfunc():
... x = 0 # x is a local
... def func1():
... global x # x is global in this scope and onwards
... def func2():
... print('func2:', x) # x is a free variable
... func2()
... print('outerfunc:', x)
... func1()
...
>>> x = 42
>>> outerfunc()
outerfunc: 0
func2: 42
>>> x = 81
>>> outerfunc()
outerfunc: 0
func2: 81
xinouterfunc是有界的,所以不是自由变量。因此,它在该范围内是本地的。但是,在 中func1,global x声明在嵌套的 scrope 中标记x为全局。Infunc2 x是一个自由变量,根据您找到的语句,它被视为全局变量。