Python3.x中的闭包和变量范围问题让我感到困惑

Python3.x中的闭包和变量范围问题让我感到困惑,python,function,variables,scope,closures,Python,Function,Variables,Scope,Closures,我正在使用Python3.7.0,我正在做一些实验来理解变量作用域的微妙之处,但我仍然不理解这种行为 当我执行此代码时: def f(): x=0 def g():y=x+1;x=y return g f()() 我得到UnboundLocalError:赋值前引用了局部变量“x” 但是,当我执行此命令时: def f(): x=0 def g():y=x+1 return g f()() def f(): x=0 def g():x=1

我正在使用Python3.7.0,我正在做一些实验来理解变量作用域的微妙之处,但我仍然不理解这种行为

当我执行此代码时:

def f():
    x=0
    def g():y=x+1;x=y
    return g
f()()
我得到UnboundLocalError:赋值前引用了局部变量“x”

但是,当我执行此命令时:

def f():
   x=0
   def g():y=x+1
   return g
f()()
def f():
   x=0
   def g():x=1
   return g
f()()
它很好用。即使是这个:

def f():
   x=0
   def g():y=x+1
   return g
f()()
def f():
   x=0
   def g():x=1
   return g
f()()

它也很好用。所以我很困惑。在我看来,如果将值
1
分配给
g
函数中的非局部变量
x
单独起作用,另一方面,如果将包含
x
的表达式分配给
g
函数中的局部变量
y
也起作用,那么指令
y=x+1
x=y
两者都应该起作用。我不明白是什么导致了这个错误。我觉得我在理解Python的行为时遗漏了一些基本的东西。

我将对此进行一次不明智的尝试。在以下代码中:

def f():
    x = 0  # assignment makes this x local to f()

    def g():
        y = x + 1
        x = y  # assignment makes this x local to g()

    return g

f()()
g()
内部的
x
赋值迫使它成为
g()
的局部变量。因此,当您访问未赋值局部变量的值时,第一行会导致错误。我相信这种“赋值使其成为局部”的逻辑并没有遵循程序的流程——函数被视为一个整体来进行判断,然后代码被逐行查看

您可以从函数访问作用域中的任何变量,但只能设置局部变量。除非已将分配的变量声明为
全局
非局部

def f():
    x = 0  # assignment makes this x local to f()

    def g():
        nonlocal x

        y = x + 1
        x = y  # x is declared to come from a nonlocal scope

    return g

f()()
在第二个示例中,这不是问题,因为您只查看
x
的值,而没有设置它,因此它可以来自任何适当的范围:

def f():
    x = 0  # assignment makes this x local to f()

    def g():
        y = x + 1  # x comes from an outer scope

    return g

f()()
最后,您的第三个示例与第一个示例相同,没有未设计的局部变量使用错误:

def f():
    x = 0  # assignment makes this x local to f()

    def g():
        x = 1  # assignment makes this x local to g()

    return g

f()()
在我看来,如果将值1赋给非局部变量 g函数中的x单独起作用


您是如何确定在
f()
中重新分配
x
效果良好的?

我将对此进行一次不明智的尝试。在以下代码中:

def f():
    x = 0  # assignment makes this x local to f()

    def g():
        y = x + 1
        x = y  # assignment makes this x local to g()

    return g

f()()
g()
内部的
x
赋值迫使它成为
g()
的局部变量。因此,当您访问未赋值局部变量的值时,第一行会导致错误。我相信这种“赋值使其成为局部”的逻辑并没有遵循程序的流程——函数被视为一个整体来进行判断,然后代码被逐行查看

您可以从函数访问作用域中的任何变量,但只能设置局部变量。除非已将分配的变量声明为
全局
非局部

def f():
    x = 0  # assignment makes this x local to f()

    def g():
        nonlocal x

        y = x + 1
        x = y  # x is declared to come from a nonlocal scope

    return g

f()()
在第二个示例中,这不是问题,因为您只查看
x
的值,而没有设置它,因此它可以来自任何适当的范围:

def f():
    x = 0  # assignment makes this x local to f()

    def g():
        y = x + 1  # x comes from an outer scope

    return g

f()()
最后,您的第三个示例与第一个示例相同,没有未设计的局部变量使用错误:

def f():
    x = 0  # assignment makes this x local to f()

    def g():
        x = 1  # assignment makes this x local to g()

    return g

f()()
在我看来,如果将值1赋给非局部变量 g函数中的x单独起作用


您是如何确定在
f()
中重新分配
x
效果良好的?

“您是如何确定在f()中重新分配x效果良好的?”对不起,我认为这是非本地的,我的错。您的回答很清楚,非常感谢。我还认为python只考虑函数中第一次出现的变量来确定作用域。但你告诉我,它首先读取函数作为一个整体来确定每个变量的作用域,然后逐行执行。我还了解到,除非将变量声明为非本地变量,否则赋值会使其成为本地变量,即使前面的语句将其视为非本地变量(我的意思是从一个未赋值的变量中读取一个值会使python查找非局部范围)。请告诉我是否仍然缺少一些内容。“您是如何确定在f()中重新赋值x的工作正常的?”很抱歉,我认为它被认为是非局部的,我的错。您的回答很清楚,非常感谢。我还认为python只考虑函数中第一次出现的变量来确定作用域。但您告诉我,它首先读取函数作为一个整体来确定每个变量的作用域,然后执行第行通过这一行,我还了解到,除非将变量声明为非本地变量,否则给它赋值会使它成为本地变量,即使前面的语句将其视为非本地变量(我的意思是从未赋值的变量中读取值会使python查找非本地范围)。请告诉我是否仍然缺少某些内容。我所说的“经验”是指“实验”,我刚刚编辑了这个问题。对不起,我把英语和法语弄混了,两者都不是我的母语。我说的“经验”是指“实验”,我刚刚编辑了这个问题。对不起,我把英语和法语弄混了,两者都不是我的母语。