关于函数:Python 3:UnboundLocalError:赋值前引用的局部变量

Python 3: UnboundLocalError: local variable referenced before assignment

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

以下代码给出了错误UnboundLocalError: local variable 'Var1' referenced before assignment

1
2
3
4
5
6
7
8
9
10
11
Var1 = 1
Var2 = 0
def function():
    if Var2 == 0 and Var1 > 0:
        print("Result One")
    elif Var2 == 1 and Var1 > 0:
        print("Result Two")
    elif Var1 < 1:
        print("Result Three")
    Var1 =- 1
function()

我怎么修这个?谢谢你的帮助!


这是因为,即使存在Var1,您也在函数内部使用名称Var1(底线是Var1 -= 1)的赋值语句。当然,这会在函数的作用域内创建一个名为Var1的变量(事实上,-=+=只会更新(重新分配)现有变量,但由于未知原因(可能在这种上下文中的一致性),python将其视为赋值。python解释器在模块加载时看到了这一点,并决定(正确地)全局作用域的Var1不应在本地作用域内使用,这会导致在本地分配变量之前试图引用该变量时出现问题。

在必要的情况下,使用全局变量通常是Python开发人员不喜欢的,因为这会导致代码混乱和有问题。但是,如果您想使用它们来完成代码所隐含的内容,您可以简单地添加:

1
global Var1, Var2

在你的功能顶部。这将告诉python您不打算在函数的本地范围内定义Var1Var2变量。python解释器在模块加载时看到这一点,并决定(正确地)在全局范围内查找对上述变量的任何引用。

一些资源

  • 对于这个常见问题,python网站有很好的解释。
  • python 3提供了一个相关的nonlocal语句——也请检查一下。


如果在函数中设置变量的值,Python会将其理解为使用该名称创建局部变量。此局部变量屏蔽全局变量。

在您的例子中,Var1被认为是一个局部变量,它在设置之前就被使用了,因此是错误。

为了解决这个问题,可以通过在函数中加入global Var1,明确地说它是全局的。

1
2
3
4
5
6
7
8
9
10
11
12
Var1 = 1
Var2 = 0
def function():
    global Var1
    if Var2 == 0 and Var1 > 0:
        print("Result One")
    elif Var2 == 1 and Var1 > 0:
        print("Result Two")
    elif Var1 < 1:
        print("Result Three")
    Var1 =- 1
function()


您可以通过传递参数而不是依赖全局参数来解决这个问题。

1
2
3
4
5
6
7
8
9
def function(Var1, Var2):
    if Var2 == 0 and Var1 > 0:
        print("Result One")
    elif Var2 == 1 and Var1 > 0:
        print("Result Two")
    elif Var1 < 1:
        print("Result Three")
    return Var1 - 1
function(1, 1)


我不喜欢这种行为,但这就是Python的工作方式。其他人已经回答了这个问题,但为了完整性,让我指出python 2有更多这样的怪癖。

1
2
3
4
5
6
7
8
9
def f(x):
    return x

def main():
    print f(3)
    if (True):
        print [f for f in [1, 2, 3]]

main()

python 2.7.6返回一个错误:

1
2
3
4
5
6
Traceback (most recent call last):
  File"weird.py", line 9, in <module>
    main()
  File"weird.py", line 5, in main
    print f(3)
UnboundLocalError: local variable 'f' referenced before assignment

python将f作为[f for f in [1, 2, 3]]中的局部变量使用,并决定它也是f(3)中的局部变量。您可以添加一个global f声明:

1
2
3
4
5
6
7
8
9
10
def f(x):
    return x

def main():
    global f
    print f(3)
    if (True):
        print [f for f in [1, 2, 3]]

main()

它确实有效;但是,F在最后变成3…也就是说,print [f for f in [1, 2, 3]]现在将全局变量f改为3,所以它不再是一个函数。

幸运的是,它在python3中在print中添加括号后运行良好。


为什么不简单地返回计算值,让调用者修改全局变量呢?在函数中操纵全局变量不是一个好主意,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
Var1 = 1
Var2 = 0

def function():
    if Var2 == 0 and Var1 > 0:
        print("Result One")
    elif Var2 == 1 and Var1 > 0:
        print("Result Two")
    elif Var1 < 1:
        print("Result Three")
    return Var1 - 1

Var1 = function()

或者甚至制作全局变量的本地副本并使用它们,然后返回调用者随后可以适当分配的结果。

1
2
3
4
5
6
def function():
v1, v2 = Var1, Var2
# calculate using the local variables v1 & v2
return v1 - 1

Var1 = function()