关于python:本地框架不能在其父框架中使用绑定的名称

local frame can't use name bound in its parent frame

本问题已经有最佳答案,请猛点这里访问。

在编程课程中遇到了Python环境概念,并有以下问题。

例如:

(1)

1
2
3
4
5
6
>>>def f(x):
       def g(y):
           return x - y
        return g
>>> f(2)(3)
-1

(2)

1
2
3
4
5
6
7
8
9
10
def f(x):
    def g(y):
        x = x - y
        return x
    return g
>>> f(2)(3)
Traceback (most recent call last):
  File"<stdin>", line 1, in <module>
  File"<stdin>", line 3, in g
UnboundLocalError: local variable 'x' referenced before assignment

(3)

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> def f(x):
        def g(y):
            if x > y:
               x = x - y
            else:
               x = y - x
            return x
        return g
>>> f(2)(3)
Traceback (most recent call last):
  File"<stdin>", line 1, in <module>
  File"<stdin>", line 3, in g
UnboundLocalError: local variable 'x' referenced before assignment

示例(1)可以从其父框架引用"x",但(2)和(3)不能引用。我不知道为什么。如果(2)由于分配给非本地名称而失败,为什么(3)在第3行给出错误,而不是第4行?


每当您在python中"引用"一个名称时,都会隐式地执行非限定名称查找。它们遵循legb规则:系统按顺序在不同的位置查找名称的绑定

  • 在执行查找的函数的本地范围内(如果有)
  • 在包含正在执行查找的函数的本地范围内(如果有)
  • 在全球范围内
  • 在内置模块中。
  • 搜索一旦找到所搜索名称的绑定,搜索就会停止。如果名称绑定在这些位置中的多个,则列表中较早的位置被称为阴影。

    在第一个代码示例中,x绑定在e/f中,y绑定在l/g中。两者都是函数的参数,函数参数都绑定在函数的局部范围内。

    在您的第二个示例中,x =在内部函数g的局部范围内绑定名称x,从而在eeclosing函数f中隐藏x的绑定。因此,legb不再在e/f中找到x,而是在l/g中找到。

    通过查看g中写入的x =python在编译时决定x的绑定来自g。不幸的是,运行时gx的绑定尚未建立。这就是为什么你会得到一个UnboundLocalError

    在第三个例子中,出现了完全相同的问题:在第4行,编译器发现在L/g中有一个x的绑定,它隐藏了E/fx的绑定,因此在运行时将使用gx的绑定。在运行时,我们到达第3行(在这里查找名称)之前的第4行(在这里名称是绑定的),因此再次访问UnboundLocalError

    错误出现在第3行,因为这是查找失败的行。

    综上所述,在g中分配x没有错。当您试图在建立g之前查找x的值时,就会出现问题。

    如果您在python 3中,可以在内部函数g中添加声明nonlocal x。这意味着:亲爱的编译器,如果在这个范围内的任何地方找到了试图绑定x的代码,就不要在这个范围内创建绑定,而是在已经提供绑定的任何封闭范围内重新绑定名称。