保留变量值的Python递归函数

时间:2015-12-29 22:07:24

标签: python recursion

我正在刷一些好的旧算法,并用python做,因为我现在经常使用它。

运行递归函数时遇到问题;每次递归函数调用自身时,变量都会重置:

def recursive_me(mystring):
    chars = len(mystring)
    if chars is 0:
        print("Done")
    else:
        first = int(str[0])
        total = + first
        print(total)
        recursive_me(mystring[1:])

recursive_me("4567")

我在这里做的是得到一个由数字组成的字符串;取第一个,将其转换为int;然后再次递归运行该函数,这样我就可以从字符串中取一个数字并将所有值相加。

理想情况下,输出应显示总数,同时它会添加所有数字(4 + 5 + 6 + 7),但是当第一次调用递归函数时,函数会重置总值。

在使用递归函数运行操作时是否习惯使用全局变量,或者我做错了什么?

5 个答案:

答案 0 :(得分:7)

您可以像这样编码:

def recursive_me(mystring):
    if mystring: # recursive case
        return int(mystring[0]) + recursive_me(mystring[1:])
    else:        # base case
        return 0

def recursive_me(mystring, total = 0):
    if mystring: # recursive case
        return recursive_me(mystring[1:], total + int(mystring[0]))
    else:        # base case
        return total

虽然这对Python没有多大帮助,因为它没有实现尾调用优化。

如果要查看中间值,请更改第二个版本:

def recursive_me(mystring, total = 0):
    if mystring: # recursive case
        newtotal = total + int(mystring[0])
        print(newtotal)
        return recursive_me(mystring[1:], newtotal)
    else:        # base case
        return total

然后

4
9
15
22
22 # this is the return value; previous output is from `print()`

答案 1 :(得分:1)

通常的做法是将这些变量保存为参数,并将它们传递给链。在您的情况下,您可能希望将total作为附加参数传递,并根据需要进行更新。

在python

中也有一个很好的功能方法
t=raw_input()
print reduce(lambda a, b: a+b, map(int,t))

这本质上是递归的。

答案 2 :(得分:1)

作为前言:在我写这个答案的同时,很多答案都收到了有意义的编辑。不要反对我。

我在这里抛出两分钱只是因为有很多过于复杂的答案。 这是OP努力的更正复制粘贴。

ViewDefinition

首先,我们检查基本情况,如果字符串中没有左字符。如果字符串长度为0,则返回总计算的ammount。

否则,我们将第一个字符转换为int,并将其添加到total。您遇到的第一个错误是您编写了def recursive_me(mystring, total=0): chars = len(mystring) if chars is 0: print("Done") return total else: first = int(mystring[0]) total += first print(total) recursive_me(mystring[1:], total) str[0]是一个内置类型的python,产生的错误类似于" str不可订阅"。

此错误表示str无法通过" []"运营商。如果您尝试执行str,则会发生同样的情况,因为1[0]是一个整数。 " []"运算符只能对列表,元组和字符串进行操作(我可能已经忘记了一些内置类型)。

您遇到的第二个错误是添加部分。您编写了1,但您正在寻找的运算符是total = + first,实际上它只是一种缩写+=的方式。

此外,您最初的问题是关于" python"忘记"总计"的价值。这是因为您必须向前传递该值,或者以强制"强制"的方式编写递归函数。它,所谓的,当场评估你对你的功能的下一次调用。

在我的例子中,我发送了函数recursive_me的下一次调用,即当前的总值。在@uselpa给出的例子中;上面他让python通过将它放在operator a = a+b之后来评估对该函数的下一次调用:

+

然后(对于return int(mystring[0]) + recursive_me(mystring[1:])

recursive_me("4567")

因为python需要在这里返回一个值,但是表达式一直在调用新函数而python不能返回,直到它将所有值都计算到最终数字(至少在这种情况下)。

答案 3 :(得分:0)

一些指示:

  • 您的默认情况应返回实际数字(在您的情况下为0)而不仅仅是打印完成。
  • total = + firsttotal设置为first,而不是将first添加到total。您需要total += first来完成后者。
  • “保留”当前总值的技巧是通过将其与每次调用一起传递,将其“保存”在递归调用链本身中。您不需要全局变量或默认参数来执行此操作。

这是一个解决方案:

def recursive_me(mystring):
    if not mystring: # True if mystring is empty
        return 0
    return int(mystring[0]) + recursive_me(mystring[1:])

print(recursive_me("4567")) # 22

答案 4 :(得分:0)

这是一个使用LEGB范围规则的解决方案,以避免在每次递归调用时创建新的字符串实例

def sum_str(mystring):
    def recursive_me(pos):
        cur_char = int(mystring[pos])
        if pos:
            return cur_char + recursive_me(pos-1)
        else:
            return cur_char
    return recursive_me(len(mystring)-1)

s = '4567'
print('summing', s)
print(sum_str(s))

但是,通过迭代字符串

也可以避免索引
def sum_str(mystring):
    def recursive_me(itx):
        try:
            cur_char = int(next(itx))
            return cur_char + recursive_me(itx)
        except StopIteration:
            return 0

    return recursive_me(iter(mystring))

显然,两种解决方案都会产生

summing 4567
22