【问题标题】:recursive function going into infinite loop despite condition check尽管条件检查,递归函数进入无限循环
【发布时间】:2021-04-26 09:37:04
【问题描述】:

我有一个清单

s = ["h", "e", "l", "l", "o"]

我尝试使用递归函数原地反转

def reverse_string4(arr, start=0):
    while start < len(arr):
        arr.insert(start, arr.pop())
        reverse_string4(arr, start + 1)

上面进入一个无限循环,但是下面这个可以工作

def reverse_string2(arr, start=0):
    if start == len(arr)-1:
        pass
    else:
        arr.insert(start, arr.pop())
        reverse_string2(arr, start + 1)

当调试开始变量增加时我很困惑,那么为什么没有终止while循环?

【问题讨论】:

  • while 是一个无限循环。循环体中没有任何内容可以使 while 条件为假。为什么你认为你需要一个while循环递归?
  • 那么当 start 变为 5 为什么不终止 while 循环?
  • 使用if 代替while 循环,因为递归中不需要while 循环。 if start &lt; len(arr): 也可以。
  • start 不会变成 5。当您递归调用 reverse_string2 时,您会使用自己的变量和自己的 start 创建一个新的函数运行。但是在最初的运行中,while 循环正在查看的 start 变量仍然具有相同的值,因此它仍然循环。
  • tldr:递归调用不是 goto。

标签: python recursion


【解决方案1】:

您可以通过添加print() 语句轻松查看发生了什么。

def reverse_string4(arr, start=0):
    print('-> arr %s, start=%i' % (arr, start))
    while start < len(arr):
        print('start %i < len(arr) %i' % (start, len(arr)))
        arr.insert(start, arr.pop())
        print('call reverse_string()')
        reverse_string4(arr, start + 1)
        print('back from call')

reverse_string4(['h', 'e', 'l', 'l', 'o'])运行它:

-> arr ['h', 'e', 'l', 'l', 'o'], start=0
start 0 < len(arr) 5
call reverse_string()
-> arr ['o', 'h', 'e', 'l', 'l'], start=1
start 1 < len(arr) 5
call reverse_string()
-> arr ['o', 'l', 'h', 'e', 'l'], start=2
start 2 < len(arr) 5
call reverse_string()
-> arr ['o', 'l', 'l', 'h', 'e'], start=3
start 3 < len(arr) 5
call reverse_string()
-> arr ['o', 'l', 'l', 'e', 'h'], start=4
start 4 < len(arr) 5
call reverse_string()
-> arr ['o', 'l', 'l', 'e', 'h'], start=5
back from call
start 4 < len(arr) 5
call reverse_string()
-> arr ['o', 'l', 'l', 'e', 'h'], start=5
back from call
start 4 < len(arr) 5
call reverse_string()
-> arr ['o', 'l', 'l', 'e', 'h'], start=5
back from call
start 4 < len(arr) 5
call reverse_string()
-> arr ['o', 'l', 'l', 'e', 'h'], start=5
back from call
start 4 < len(arr) 5
call reverse_string()
-> arr ['o', 'l', 'l', 'e', 'h'], start=5
back from call
start 4 < len(arr) 5
call reverse_string()

看到了吗? while 条件仍然成立,所以它停留在 while 循环中。

正确的解决方法是使用 任一 while 循环或递归(然后,可能是 return 递归调用调用的值)。

【讨论】:

  • 谢谢,我注意到在调试窗口中,一旦开始变成 5,它就会回到 4 并且无限。那么你的意思是while和递归调用不应该一起使用吗?我是这样理解的。
  • 这基本上就是要点,是的。将两者结合起来并非不可能,但如果您只是学习,可能甚至不要尝试。标准逻辑只是if (something): return recursive_call(): else: return base case,而递归负责处理任何(隐式)循环。
  • 谢谢,是的,我正在学习和练习各种练习。
  • 如果这解决了您的问题,请考虑投票和/或接受它。或者,您可以发布自己的答案并接受。接受答案通过将问题标记为已解决来帮助未来的访问者。另见help.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-16
  • 1970-01-01
  • 2011-08-18
  • 2021-12-06
  • 1970-01-01
相关资源
最近更新 更多