python中的UnboundLocalError令人困惑

时间:2012-10-01 12:16:41

标签: python

任何人都可以解释以下代码的异常。它仅在我将display()中的var sub更改为其他名称时才有效。也没有全局变量sub。那发生了什么?

def sub(a, b):
    return a - b

def display():
    sub = sub(2,1) // if change to sub1 or sth different to sub, it works
    print sub

4 个答案:

答案 0 :(得分:2)

您在范围内分配的任何变量都被视为局部变量(除非您将其声明为global,或者在python3中,nonlocal),这意味着它不会在周围查找作用域。

具有相同错误的简化示例:

def a(): pass

def b(): a = a()

现在,请考虑这里涉及的不同范围:

全局命名空间包含ab

函数a不包含局部变量。

函数b包含对a的赋值 - 这意味着它被解释为局部变量并从外部范围隐藏函数a(在本例中为全局范围) )。由于a在调用之前未在b内定义,因此它是未绑定的局部变量,因此是UnboundLocalError。这与你写下这个完全相同:

def b(): x = x()

解决方案很简单:为sub电话的结果选择其他名称。

重要的是要注意使用和分配的顺序没有区别 - 如果您编写如下函数,错误仍然会发生:

def display():
    value = sub(2,1)         #UnboundLocalError here...
    print value
    sub = "someOtherValue"   #because you assign a variable named `sub` here

这是因为当python解释器创建函数对象时会生成局部变量列表。

答案 1 :(得分:1)

这最初是评论。 OP发现这有用作为答案。因此,我将其重新发布为答案

最初,sub是一个功能。然后,它成为函数的返回值。所以当你说print sub时,python不知道你指的是sub

修改

首先定义一个函数sub。现在,python知道sub是什么。

当你创建一个变量并尝试赋值给它时(比如x = 2),python会评估=右边的东西,并将评估的值赋值为=左侧的内容。因此,右侧的所有内容都应该实际计算。

因此,如果您的陈述是x = x+1,那么x最好在该行之前为其分配一个值;以前定义的x必须与添加1的某种类型兼容。

但是假设x是一个函数,你在一些其他函数中创建一个名为x的变量,并尝试赋值给它一个用函数x计算的值,然后这个真的开始混淆python关于你指的是哪个x。这实际上是对this answer的过度简化,它在解释python函数中的变量范围和阴影方面做得更好

答案 2 :(得分:1)

对于使用的每个变量,Python确定它是本地变量还是非本地变量。引用未知变量会将其标记为非本地变量。以后重用与本地变量相同的名称被认为是程序员的错误。

考虑这个例子:

def err():
    print x # this line references x
    x = 3   # this line creates a local variable x
err()

这会给你

Traceback (most recent call last):
  File "asd.py", line 5, in <module>
    err()
  File "asd.py", line 2, in err
    print x # this line references x
UnboundLocalError: local variable 'x' referenced before assignment

基本上,Python会跟踪代码中对名称的所有引用。当它读取行print x时,Python知道x是来自外部范围(upvalue或global)的变量。但是,在x = 3 xUnboundLocalError用作局部变量。由于这是代码中的不一致,Python引发{{1}}以引起程序员的注意。

答案 3 :(得分:-1)

Python开始执行代码并首先获得函数

def sub(a, b):
    return a - b

因此在执行此解释器后,将sub作为函数。现在来到下一行它找到了

def display():
    sub = sub(2,1) // if change to sub1 or sth different to sub, it works
    print sub

因此第一行sub = sub (2, 1)会将sub函数转换为sub变量。从此函数返回sub变量。所以它的创造问题。