【问题标题】:python recursive function error RuntimeError: maximum recursion depth exceededpython递归函数错误RuntimeError:超出最大递归深度
【发布时间】:2013-05-16 00:11:37
【问题描述】:

我有这个脚本:

def number_of_occurences(c, message):
  position = message.find(c)
  if position == -1:
    return 0
  else:
    if len(message[position:]) == 0:
      return position
    else:
      return position + number_of_occurences(c, message[position:])

number_of_occurences('a', 'azertya')

但是当我运行它时,我得到了这个错误:

Traceback (most recent call last):
  File "frequency_analysis.py", line 31, in <module>
    number_of_occurences('a', 'azertya')
  File "file_name.py", line 29, in number_of_occurences
    return position + number_of_occurences(c, message[position:])
...
...
...
  File "file_name.py", line 29, in number_of_occurences
    return position + number_of_occurences(c, message[position:])
RuntimeError: maximum recursion depth exceeded

我知道这个similar question,但它没有帮助,花了更长的时间,但给出了同样的错误:

sys.setrecursionlimit(10000)

还有这个:

sys.setrecursionlimit(30000)

但是对于这个:

sys.setrecursionlimit(50000)

它给出了这个错误:

分段错误(核心转储)

我在这里做错了什么?提前致谢。

更新:

感谢@abarnet,这是正确的代码:

def number_of_occurences(c, message):
  position = message.find(c)
  nbr = 0.0
  if position == -1:
    return 0
  else:
    nbr += 1
    if len(message[position:]) == 0:
      return nbr
    else:
      return nbr + number_of_occurences(c, message[position + 1:])

【问题讨论】:

  • 在什么方面没有帮助?
  • 花费了更长的时间但给出了同样的错误。
  • 问题是(a)递归限制太低,因为你需要,比如说,20000? (b) 你认为你的代码中的递归深度远低于任何合理的限制(比如低于 10)? (c) 你知道你得到了无限或太深的递归,并想知道你的代码为什么这样做?
  • 如果 position 等于 0,那么你将继续递归调用。
  • 尽管有一些函数式风格原语,Python 缺乏纯函数式语言中常见的尾调用优化。大多数时候,以迭代的方式重写任何递归算法是微不足道的,这是 Python 中的惯用形式。

标签: python recursion python-2.7


【解决方案1】:

问题是你用相同的参数递归调用自己,这保证了无限递归。将递归限制设置多高并不重要;您不能将其设置为无穷大。*


使用您的参数手动跟踪它。

position = message.find(c) # = 'azertya'.find('a') = 0
if position == -1: # Nope
else:
    if len(message[position:]) == 0: # len('azertya'[0:]) == len('azertya') == 7 != 0
    else:
        return position + number_of_occurences(c, message[position:])
            # 0 + number_of_occurences('a', 'azertya'[0:])
            # == 0 + number_of_occurences('a', 'azertya')
            # which is exactly what we were called with

即使你不从第一个字符开始,如果你从字符串中的 any 字符开始,你最终会到达那一点,并且遇到同样的问题。再次尝试使用'r' 而不是'a' 进行跟踪。

通过像 this one 这样的交互式可视化工具运行比手动跟踪要简单得多(而且更漂亮,更难搞砸)。

或者,尝试 print 每次通过 cmessageposition,应该很明显会发生什么。

修复非常简单:

return position + number_of_occurences(c, message[position+1:])

* 即使你可以,一旦堆栈与堆发生冲突,你就会得到一个段错误,至少在 CPython 中是这样。这就是为什么你得到一个只有 50000 的段错误。但即使使用不同的实现,如 Stackless 或 PyPy,一旦没有更多堆栈帧的空间,你也会得到一个内存错误。但是,如果您有无限位的寻址和无限的虚拟页表空间,那么这不是问题,并且愿意永远等待......它仍然不会工作,但至少它永远不会失败.

【讨论】:

    猜你喜欢
    • 2019-07-03
    • 2017-03-18
    • 2015-04-15
    • 1970-01-01
    • 1970-01-01
    • 2011-01-24
    • 2013-02-20
    • 2023-01-30
    • 2016-12-10
    相关资源
    最近更新 更多