自由变量在Python中被视为全局变量吗?

时间:2018-10-05 13:18:22

标签: python python-3.x scope globals free-variable

在Python 3.7参考手册的Execution Model section中,我读了以下语句:

  

global语句的作用域与同一块中的名称绑定操作相同。如果自由变量的最近封闭范围包含global语句,则将自由变量视为全局变量。

因此,我在Python解释器中输入了以下代码:

x =0
def func1():
    global x
    def func2():
        x = 1
    func2()

在调用func1()之后,我希望全局范围内的x的值更改为1

我怎么了?

1 个答案:

答案 0 :(得分:3)

x = 1中的

func2不是自由变量。这只是另一个当地人。除非另有说明,否则您将绑定到该名称,默认情况下,绑定的名称是本地人。

来自same Execution model documentation

  

如果名称绑定在块中,则除非声明为nonlocalglobal,否则它是该块的局部变量。 [...] 如果在代码块中使用了变量但未在代码块中定义,则它是一个自由变量。

粗体强调我

您在块中用x = 1绑定了名称,因此它是该块中的局部变量,并且不能是自由变量。因此,您发现的部分不适用,因为这仅适用于自由变量:

  

如果自由变量的最近封闭范围 包含global语句,则将自由变量视为全局变量。

您不应在x中绑定func2(),因为只有在范围内 not 绑定的名称才是自由变量。

这可行:

>>> def func1():
...     global x
...     x = 1
...     def func2():
...         print(x)  # x is a free variable here
...     func2()
...
>>> func1()
1
>>> x
1
x中的

func2现在是一个自由变量;它未在func2的范围内定义,因此请从父范围中选取它。此处的父作用域为func1,但是x在此处被标记为全局,因此当对x函数进行读取 print()时,将使用全局值

与此相反,xfunc1中未被标记为全局变量:

>>> 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,但这不会影响打印的内容。 x中的func2是一个自由变量,但是父范围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
x中的

outerfunc是绑定的,因此不是自由变量。因此,它在该范围内是本地的。但是,在func1中,global x声明将x标记为嵌套scrope中的全局变量。 func2中的x是一个自由变量,根据您找到的语句,它被视为全局变量。