Python中的递归? RuntimeError:调用Python对象时超出了最大递归深度

时间:2013-01-08 19:17:18

标签: python recursion runtime-error simulation vpython

  

可能重复:
  Maximum recursion depth?

我的代码有另一个问题。 我正在研究我在Vpython中的第一个程序,我必须模拟混合两种气体。首先我遇到了边界问题,但现在当球(代表气体粒子)留在边界内时,存在不同的错误。几秒钟后,我收到一个错误,该错误显示在我的函数的源代码下面。 代码:

def MovingTheBall(listOfBalls,position,numCell,flagOfExecution):
    flag = 0
    if flagOfExecution==0:
        positionTmp = position
    else:
        positionTmp = (position[0]+choice([-1,0,1]),position[1]+choice([-1,0,1]),0)
    for i in range( 0, len(listOfBalls) ):
        if positionTmp==listOfBalls[i].pos:
            flag=1


    if flag==1:
        return MovingTheBall(lista,(position[0]+choice([-1,0,1]),position[1]+choice([-1,0,1]),0),numCell,1)
    else:
        if positionTmp[0]==0 or positionTmp[0]>=numCell or positionTmp[0]<=-numCell or positionTmp[1]>=numCell or positionTmp[1]<=-numCell:
            return MovingTheBall(lista,(position[0]+choice([-1,0,1]),position[1]+choice([-1,0,1]),0),numCell,1)

        return positionTmp

错误是:

    return MovingTheBall(listOfBalls,(position[0]+choice([-1,0,1]),position[1]+choice([-1,0,1]),0),numCell,1)
  File "gaz.txt", line 138, in MovingTheBall
    return MovingTheBall(listOfBalls,(position[0]+choice([-1,0,1]),position[1]+choice([-1,0,1]),0),numCell,1)
  File "gaz.txt", line 138, in MovingTheBall
    return MovingTheBall(listOfBalls,(position[0]+choice([-1,0,1]),position[1]+choice([-1,0,1]),0),numCell,1)
  File "gaz.txt", line 138, in MovingTheBall
    return MovingTheBall(listOfBalls,(position[0]+choice([-1,0,1]),position[1]+choice([-1,0,1]),0),numCell,1)
  File "gaz.txt", line 138, in MovingTheBall
    return MovingTheBall(listOfBalls,(position[0]+choice([-1,0,1]),position[1]+choice([-1,0,1]),0),numCell,1)
  File "gaz.txt", line 138, in MovingTheBall
    return MovingTheBall(listOfBalls,(position[0]+choice([-1,0,1]),position[1]+choice([-1,0,1]),0),numCell,1)
  File "gaz.txt", line 130, in MovingTheBall
    if positionTmp==listOfBalls[i].pos:
RuntimeError: maximum recursion depth exceeded while calling a Python object

有人能想出一种简化我的功能的方法吗?

我在循环时运行它的功能:

while 1:
        rate(20)
        for i in range(0,len(self.listOfBalls)):
            self.listOfBalls[i].pos=poruszanie(self.listOfBalls,self.listOfBalls[i].pos,self.numCell,0)

4 个答案:

答案 0 :(得分:26)

Python缺乏像lisp这样的函数式语言中常见的尾递归优化。在Python中,递归仅限于999次调用(参见sys.getrecursionlimit)。

如果999深度超出了您的预期,请检查实现是否缺少阻止递归的条件,或者在某些情况下此测试可能是错误的。

我敢说,在Python中,纯递归算法实现不正确/安全。限制为999的fib()实现并不正确。总是可以将递归转换为迭代,这样做是微不足道的。

经常没有达到它,因为在许多递归算法中,深度往往是对数的。如果您的算法不是这种情况,可能会有超过999深度的递归调用,您有两种选择:

1)您可以使用sys.setrecursionlimit(n)更改递归限制,直到您的平台允许的最大值:

  

sys.setrecursionlimit(limit)

     

将Python解释器堆栈的最大深度设置为limit。此限制可防止无限递归导致C堆栈溢出并导致Python崩溃。

     

可能的最高限制取决于平台。当用户具有需要深度递归的程序和支持更高限制的平台时,用户可能需要将限制设置得更高。这应该小心,因为过高的限制可能导致崩溃。

2)您可以转换为将算法从递归转换为迭代。如果递归深度大于平台允许的深度,则是解决问题的唯一方法。如果您遇到问题,请发布一个新问题,以便我们提供帮助。

答案 1 :(得分:5)

我已经将递归更改为迭代。

def MovingTheBall(listOfBalls,position,numCell):
while 1:
    stop=1
    positionTmp = (position[0]+choice([-1,0,1]),position[1]+choice([-1,0,1]),0)
    for i in range(0,len(listOfBalls)):
        if positionTmp==listOfBalls[i].pos:
            stop=0
    if stop==1:
        if (positionTmp[0]==0 or positionTmp[0]>=numCell or positionTmp[0]<=-numCell or positionTmp[1]>=numCell or positionTmp[1]<=-numCell):
            stop=0
        else:
            return positionTmp

效果很好:D

答案 2 :(得分:4)

错误是堆栈溢出。那应该在这个网站上响铃,对吗?之所以发生这种情况,是因为对poruszanie的调用导致对poruszanie的另一次调用,递归递增深度为1.第二次调用导致对同一函数的另一次调用。这种情况一次又一次地发生,每次递增递归深度。

现在,程序的可用资源有限。每个函数调用在所谓的堆栈之上占用一定量的空间。如果达到最大堆栈高度,则会出现堆栈溢出错误。

答案 3 :(得分:0)

当函数对自身进行过多的递归调用时,会出现错误。它可能是这样做的,因为基本情况永远不会得到满足(因此它会陷入无限循环)或只是通过对自身进行大量调用。您可以使用while循环替换递归调用。