try、 except、finally 中的While 循环与递归差异处理

问题描述 投票:0回答:3

while
try
except
错误处理中使用
finally
循环与递归有何区别?

当我在用户输入错误处理中使用

while
循环时:

while True:
    try:
        user_num = float(input("Enter a number: ")
        break
    except ValueError as e:
        print("That is not a number. Error:", e)
    finally:
        print("Cycle is done.")

代码循环直到没有错误并且每个循环打印

"Cycle is done."

当我使用递归而不是

while
循环时:

try:
    user_num = float(input("Enter a number: ")
except ValueError as e:
    print("That is not a number. Error:", e)
    get_num()
finally:
    print("Cycle is done.")

代码循环直到没有错误为止,成功后会打印

"Cycle is done."
* n,其中 n = 循环数。

最初我希望它们运行相同。 看起来

while
循环会在循环之前到达
finally
部分,并且递归方法仍在执行
except
代码,因此成功后,每次调用都会按 LIFO 顺序到达
finally

我读到,如果循环足够长的时间,递归方法最终会引发

RecursionError: maximum recursion depth exceeded
错误。

这两种循环错误处理方法还有其他区别吗?

python recursion error-handling while-loop finally
3个回答
0
投票

正如评论者指出的,这个问题可以通过了解调用堆栈和迭代与递归来回答。我将用我对这些主题的研究中的相关关键要点来回答我的问题:

函数内的迭代不会添加到调用堆栈中,但函数内的递归调用会添加到调用堆栈中。每次递归都会向占用内存的调用堆栈添加一个堆栈帧。值得一提的是,Python 并不是为了优化尾递归而设计的,以保持准确的回溯。当达到 1000 的递归限制时,Python 会引发

RecursionError
来防止 堆栈溢出 。 因此,即使具有相同的 Big O 表示法,迭代也会更快且空间效率更高。 递归可以使用参数将信息传递给子函数调用,也可以使用返回值将信息传递回父调用函数。这使得对树和图执行操作变得更容易。

虽然没有万能的答案,但在大多数情况下,迭代是更好的选择,特别是当目标是重复代码直到某个条件变为 False 时,就像在我的示例中一样。 然而,递归对于导航非线性数据结构以及在问题可以分解为更小的部分的情况下非常有用。


0
投票

finally
代码块仅在
except
完成后执行。但是请使用虚拟
returnToStart
方法查看这两个代码。

当你运行一段时间后,python 会运行类似的东西:

try:
    user_num = float(input("Enter a number: ")
    break
except ValueError as e:
    print("That is not a number. Error:", e)
finally:
    print("Cycle is done.")
if notBreaked():
    returnToStart()

第二个代码将执行此操作:

try:
    user_num = float(input("Enter a number: ")
    break
except ValueError as e:
    print("That is not a number. Error:", e)
    returnToStart()
finally:
    print("Cycle is done.")

因此,在每次调用该函数之前,

except
代码块都不会终止。因此,所有
finally
只会在每个
get_num()
调用终止
except
代码块

之后发生

-2
投票

当您存储中间值时,递归最有用。在像 C 这样的语言中,堆栈帧和函数调用都是轻量级的,因此递归是有意义的。不过,您必须小心,因为中间堆栈帧中的所有数据都保留在内存中,直到递归最终倒回。但与保存从堆分配的中间数据结构的扩展列表相比,它仍然很好。

Python 不同。 Python 的“堆栈框架”实际上是一个函数对象列表 - 为每个函数调用创建一个函数对象。它并不比在 while 循环中存储中间值的列表更好。因此,递归没有任何好处。这是一个强有力的声明,也许有一些用途,但通常不会。

就您而言,您不关心中间的错误答案。但在递归情况下,您将保留所有这些加上异常帧,直到递归倒回。这在 Python 或 C 中内存效率不高。

© www.soinside.com 2019 - 2024. All rights reserved.