任何人都可以解释以下代码的异常。它仅在我将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
答案 0 :(得分:2)
您在范围内分配的任何变量都被视为局部变量(除非您将其声明为global
,或者在python3中,nonlocal
),这意味着它不会在周围查找作用域。
具有相同错误的简化示例:
def a(): pass
def b(): a = a()
现在,请考虑这里涉及的不同范围:
全局命名空间包含a
和b
。
函数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
x
中UnboundLocalError
用作局部变量。由于这是代码中的不一致,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
变量。所以它的创造问题。