“分配之前引用的局部变量”

问题描述:

我来自沉重的Java和PHP体验之地,所以说到Python时,大部分规则对我来说都没有意义。“分配之前引用的局部变量”

下面我有一个递归斐波那契功能吐出错误:因为电话是一个全局变量

calls = 0 

def fibcount(n): 
    calls += 1 
    if n < 2: 
     return (1,1) 
    f1,c1 = fibcount(n-1) 
    f2,c2 = fibcount(n-2) 
    return (f1+f2,c1+c2+1) 

print fibcount(27),"took",calls,"calls." 

在Java中,这显然会工作:

Traceback (most recent call last): 
    File "C:\Users\Nic\workspace\lab8\src\Main.py", line 26, in <module> 
    print fibcount(27),"took",calls,"calls." 
    File "C:\Users\Nic\workspace\lab8\src\Main.py", line 19, in fibcount 
    calls += 1 
UnboundLocalError: local variable 'calls' referenced before assignment 

这里是我的代码关于函数fibcount(),所以它让我困惑,调用不在范围之内。

我在做什么错?

在Python中,您需要将全局变量声明为全局函数内部的函数,并将它们重新分配给不同的值。你可以使用global此:

def fibcount(n): 
    global calls 
    ... 

否则,Python会对待calls变量,就好像它是本地。

但请注意,您只需要为您重新分配的全局变量执行此操作。简单阅读他们的价值观将工作正常。

此外,像这样重新分配全局变量在Python中被认为是丑陋的,应尽可能地避免。大多数情况下,您应该坚持将值传递给函数,然后将变量重新分配给它们的返回值。如果您需要维护状态,请使用班级。

全局变量在Python中唯一的保证是当你想拥有模块级别的常量时。在这种情况下,惯例是他们应该有全部大写的名字:

MYCONST = 12345 
+0

我认为很明显,只有在读取值时才需要'global'关键字。然而,我认为我们需要小心“修改”这个词,因为来自许多其他语言的人在重新绑定和变异之间没有很强的心理区别(并且会考虑这两个事情“修改”)。如果我们正在重新命名*(又名*重新分配*)这个名字,我们只需要'全球'。我们可以对全局对象进行*变异(例如,如果'calls'是一个列表,我们可以追加或删除它的元素,而不需要'global'关键字)。 – 2014-12-05 17:57:00

+0

在那里,我将“修改”更改为“重新分配”。我试图避免讨论“Python没有变量,它有名称”,因为这可能会混淆OP。这里的重要部分是使用'global'关键字。关于为什么的确切细节超出了我的答案范围。 :) – iCodez 2014-12-05 18:03:50

+0

我完全赞赏不想打开那个蠕虫罐!为此,我认为尽可能使用尽可能精确的术语为罐头提供了保持关闭的最佳机会。我明白,有时候,如果你不知道更多的理解,你就不能向别人解释某些事情,但在这种情况下,*重新分配*是一个不错的选择:它可以在不增加冗长的情况下提高精度。 – 2014-12-05 18:19:58