我是python初学者,目前我正在努力学习python递归函数:
x = 10
n = 3
def rec(x,n):
if n>0:
#global x2
x2 = x*n
return rec(x2,n-1)
else:
return x2
# function call:
fcall = rec(x,n)
print fcall
让我困惑的是global x2
行。有了它,函数运行良好,按预期返回60
,但没有它,我会收到一条错误消息:
Local variable 'x2' referenced before assignment
为什么会这样?似乎一旦n
达到3
的值,并且执行了else
条件,它就不知道x2
是什么?
如果省略global
,则该变量应在该函数的本地范围内。这意味着它需要被分配到某个地方才能真正存在。由于唯一的赋值是当n > 0
条件为true时,return x2
将始终尝试返回一个不存在的变量。
当您添加global
时,您将该变量放入全局范围,使其在任何地方都可用。因此,它被分配并可以返回。
然而,让函数依赖于这样的全局变量并不是一个好主意。似乎很不明显,它需要一个全局变量才能工作。事实上,这里没有必要:您希望引用x
而不是x2
。
def rec (x, n):
if n > 0:
x = x * n
return rec(x, n - 1)
else:
return x
这样,只要n
仍然大于零,就可以将当前x
乘以n
,并将其临时重新分配给x
,然后将其传递给递归调用。如果n
等于零,则适用else
的情况,并且只返回传递给函数的当前x
。
您的问题是x2只是一个局部变量,所以当您调用函数时,它不再知道旧的x2。
通过添加全局x2,您可以将该变量放入全局空间,因此现在函数可以识别它。
看看这个:http://gettingstartedwithpython.blogspot.de/2012/05/variable-scope.html
您实际想要返回的是x,而不是x2,因为您正在将x2的值传递到递归的下一个调用中。
def rec(x,n):
if n>0:
x2 = x*n
return rec(x2,n-1)
else:
return x
如果没有global x2
,分配给x2
将创建一个新的局部变量。有了它,分配给x2
会更改全局x2
变量。这只适用于赋值,而不适用于查找变量。
当函数返回时,当前堆栈帧(以及与之相关的所有局部变量)将消失,但全局变量将永远存在(使用它们也会感到非常糟糕)。
您还可以将rec
函数代码重构为:
def rec(x, n):
return rec(x*n, n-1) if n else x
对于初学者来说,问题的一个典型原因是使用过多变量的习惯。这会使事情变得更加复杂和难以理解。你的代码可以变得更简单,如下所示:
def rec(x, n):
if n > 0:
return rec(x*n, n-1)
return x
甚至是这样,使用三元运算符:
def rec(x, n):
return rec(x*n, n-1) if n > 0 else x
然后你可以尝试一下:
rec(3, 10)
你越早养成只在需要时创建新变量的习惯,或者提高代码的可读性,你的程序就越容易编写、调试和读取。