18

可能重复:
最大递归深度?

我的代码还有另一个问题。我正在用 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

4 回答 4

43

Python 缺乏函数式语言(如 lisp)中常见的尾递归优化。在 Python 中,递归限制为 999 次调用(请参阅sys.getrecursionlimit)。

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

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

它不经常达到,因为在许多递归算法中,深度往往是对数的。如果您的算法不是这种情况,并且您希望递归比 999 调用更深,那么您有两种选择:

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

sys.setrecursionlimit(limit)

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

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

2)您可以尝试将算法从递归转换为迭代。如果递归深度大于您的平台允许的深度,这是解决问题的唯一方法。互联网上有分步说明,对于受过一些 CS 教育的人来说应该是一个简单的操作。如果您对此有疑问,请发布一个新问题,以便我们提供帮助。

于 2013-01-08T19:45:38.573 回答
10

我已将递归更改为迭代。

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

于 2013-01-08T20:10:47.067 回答
7

错误是堆栈溢出。这应该在这个网站上敲响警钟,对吧?发生这种情况是因为对 的调用poruszanie导致对 的另一个调用poruszanie,递归深度增加 1。第二次调用导致对同一函数的另一个调用。这种情况一遍又一遍地发生,每次都会增加递归深度。

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

于 2013-01-08T19:40:00.980 回答
1

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

于 2013-01-08T20:03:30.560 回答