python递归函数错误RuntimeError:超出最大递归深度

时间:2013-05-16 00:11:37

标签: python recursion python-2.7

我有这个脚本:

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:])

1 个答案:

答案 0 :(得分:5)

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


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

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

即使你没有从第一个字符开始,如果你从字符串中的任何字符开始,你最终会达到这一点,并遇到同样的问题。再次尝试使用'r'代替'a'进行跟踪。

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

或者,每次尝试print cmessageposition,这应该是显而易见的。

修复非常简单:

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

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