【问题标题】:Is there a reason not to use recursion when ensuring valid user input in Python?在确保 Python 中的有效用户输入时,是否有理由不使用递归?
【发布时间】:2017-02-13 08:22:58
【问题描述】:

我在 Python 方面相当有经验,但是当我帮助一位朋友编写脚本时,我注意到他以不同于我熟悉的方式解决了一个常见问题。他确保用户输入的格式有效(浮点数);我已经习惯了看到这样的事情,这也是我能找到的所有答案所说的:

def get_input()
    while True:
        try:
            val = float(input("input pls"))
            return val
        except:
            print("not valid, try again)

然而,他使用递归解决了这个问题,如下所示:

def get_input():
    try:
        val = float(input("input pls"))
        return val
    except:
        print("not valid, try again")
        return get_input()

这有什么缺点吗?

【问题讨论】:

  • 嗯,这可能与这个特定的用例无关,但在 python 中有一个最大的递归深度。这两个版本都受到了一个赤裸裸的except 子句的影响,不过......
  • 比较两组代码。问问自己递归版本是否更易于阅读和支持。如果不是,那么保持堆栈状态是不必要的开销。递归只有在简化时才值得。
  • 与大多数编译语言不同,Python 无法优化递归。它还规定了最大递归深度(默认为 1000)以阻止失控函数消耗所有 RAM。因此,如果可以使用像 while 循环这样的简单替代方法,则应避免 Python 中的递归。当然,如果递归适用于问题领域,例如处理递归结构,如树,那么一定要使用它。
  • @juanpa.arrivillaga:我知道有一个最大深度,但在这里并没有真正看到它的相关性。另外,我知道except 是赤裸裸的,我只是输入了一些简短的sn-ps 来演示这个案例。编辑:没关系,我知道它是如何相关的,因为每个输入都会创建一个新堆栈。 @cdarke:我个人认为递归版本看起来更干净,这就是为什么我要问它是否有任何缺点,因为我更习惯于看到循环版本。

标签: python validation recursion input


【解决方案1】:

关于此的一些问题或数据:

  1. 存在递归限制(非常高,但可能会超过)
  2. 每次递归调用 get_input 方法时,它都会为作用域创建一个新堆栈,甚至会链接 try...except 块,这对于内存使用和性能来说都是很糟糕的。
  3. 递归方法通常更难调试。

但既然它看起来像一个玩具例子,也许这无关紧要。

【讨论】:

    【解决方案2】:

    我个人不会在 Python 中这样做,尽管对我来说它看起来很容易阅读。 python的问题在于它没有尾调用优化,这里的方法将由编译器优化,因为你要做的最后一件事是返回值。

    要完成这项工作,您可以使用基于生成器的方法,以便用户出错的次数与程序是否可以处理无关。 (这看起来不像您给出的解决方案那么优雅,但确实处理了无限递归)

    def get_input_from_keyboard():
        # I have used raw_input instead of input as I am using python 2.7
        return float(raw_input("input pls"))
    
    def try_again():
        print("not valid, try again")
        for x in get_input():
            yield x
    
    def get_input():
        try:
            yield get_input_from_keyboard()
    
        except ValueError:
            for x in try_again():
                yield x
    
    
    list[get_input()][0]
    

    也就是说,您提供的递归方法可以通过捕获 RuntimeError 异常来进行调整,但这非常冒险,因为除了堆栈溢出之外,确实存在一些问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-02
      • 1970-01-01
      • 1970-01-01
      • 2013-07-28
      • 1970-01-01
      • 1970-01-01
      • 2020-09-21
      • 1970-01-01
      相关资源
      最近更新 更多