【问题标题】:Python recursion function issue [duplicate]Python递归函数问题[重复]
【发布时间】:2013-12-26 23:36:10
【问题描述】:

我是 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 是什么?

【问题讨论】:

标签: python function variables recursion global


【解决方案1】:

如果您省略了global,则该变量应位于该函数的本地范围内。这意味着它需要被分配到某个地方才能真正存在。由于唯一的赋值是当n > 0 条件为真时,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 等于 0,则适用 else 的情况,您只需返回传递给函数的当前 x

【讨论】:

  • 感谢您的回复。有趣的是,在查看有关全局变量与局部变量的教程时,它们总是会为您提供一个简单(非递归函数)的示例。所以剩下的部分是:递归函数中的局部函数在范围内是局部的,只有当前递归(如果我可以使用该术语)而不是所有递归(啊,甚至是最坏的术语,对不起)?
  • 函数中的局部变量只对该函数的当前执行可见是的。因此,如果您想将任何值传递到下一次递归,则必须在递归调用中传递这些值。
【解决方案2】:

您的问题是 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

【讨论】:

  • 谢谢伊塞特。所以基本上从else 返回的x 是作为rec() 函数的参数传入的最后一个x2
  • 没错。这就是递归的魔力:)。 x'es 冒泡直到达到“中断”条件。比他们一路上升。
  • 是的,但这对我们这些非程序员来说就像火箭科学
【解决方案3】:

如果没有global x2,分配给x2 会创建一个新的局部变量。有了它,分配给x2 使其更改全局x2 变量。这仅适用于赋值,不适用于查找变量。

当函数返回时,当前堆栈帧(以及与之关联的所有局部变量)会消失,但全局变量会永远存在(and you should also feel very bad for using them)。

【讨论】:

    【解决方案4】:

    您还可以将rec 功能代码重构为:

    def rec(x, n):
        return rec(x*n, n-1) if n else x
    

    【讨论】:

    • 如果n为负数会怎样?
    • 我认为,它假设n总是> = 0,否则为了防止最大递归错误,if的条件必须是if n>0
    【解决方案5】:

    对于初学者来说,问题的一个典型原因是使用太多变量的习惯。这会使事情变得更加复杂和难以理解。您的代码可以像这样变得更简单:

    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)
    

    您越早养成只在需要时创建新变量或提高代码可读性的习惯,您的程序就越容易编写、调试和阅读。

    【讨论】:

    • 感谢dansalmo的回复。我什至不是程序员,我也不打算为了生活而这样做。但我认为这些年来至少学习一门编程语言是非常可取的。我选择了 Python。由于我不打算成为一名专业人士,因此在这种情况下我将坚持使用 2 个变量 - 它将使我能够了解到底发生了什么,以及通过了什么。而不仅仅是在函数内部使用/传递一个变量。至少在 Isset 的回复中,我仍在试图弄清楚这一点。
    猜你喜欢
    • 1970-01-01
    • 2022-01-07
    • 2017-05-07
    • 2016-05-06
    • 2015-01-27
    • 2011-11-21
    • 1970-01-01
    • 2022-08-13
    • 2020-08-24
    相关资源
    最近更新 更多