Recursie in Python? RuntimeError: maximale recursiediepte overschreden tijdens het aanroepen van een Python-object

Mogelijk duplicaat:
Maximale recursiediepte?

Ik heb een ander probleem met mijn code.
Ik ben mijn eerste programma in Vpython aan het schrijven en ik moet een simulatie maken van het mengen van twee gassen. Eerst had ik een probleem met grenzen, maar nu als de ballen (die de gasdeeltjes vertegenwoordigen) binnen de grenzen blijven, is er iets anders mis. Na een paar seconden krijg ik een foutmelding, die wordt weergegeven onder de broncode van mijn functie.
Code:

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

de fout is:

   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

Kan iemand een manier bedenken om mijn functie te vereenvoudigen?

Ik voer de functie it while-lus uit:

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)

Antwoord 1, autoriteit 100%

Python mist de staartrecursie-optimalisaties die gebruikelijk zijn in functionele talen zoals lisp. In Python is recursie beperkt tot 999 aanroepen (zie sys.getrecursionlimit).

Als 999 diepte meer is dan u verwacht, controleer dan of de implementatie een voorwaarde mist die recursie stopt, of dat deze test in sommige gevallen verkeerd kan zijn.

Ik durf te zeggen dat in Python pure recursieve algoritme-implementaties niet correct/veilig zijn. Een fib()-implementatie beperkt tot 999 is niet echt correct. Het is altijd mogelijk om recursief in iteratief om te zetten, en dat is triviaal.

Het wordt niet vaak bereikt omdat in veel recursieve algoritmen de diepte logaritmisch is. Als dit niet het geval is met uw algoritme en u verwacht een recursie dieper dan 999 aanroepen, heeft u twee opties:

1) U kunt de recursielimiet wijzigen met sys.setrecursionlimit(n)tot het maximum dat is toegestaan voor uw platform:

sys.setrecursionlimit(limit):

Stel de maximale diepte van de Python-interpreterstack in om te beperken. Deze limiet voorkomt dat oneindige recursie een overloop van de C-stack veroorzaakt en Python laat crashen.

De hoogst mogelijke limiet is platformafhankelijk. Een gebruiker moet mogelijk de limiet hoger instellen wanneer ze een programma heeft dat diepe recursie vereist en een platform dat een hogere limiet ondersteunt. Dit moet met zorg gebeuren, omdat een te hoge limiet tot een crash kan leiden.

2) U kunt proberen het algoritme om te zetten van recursief naar iteratief. Als de recursiediepte groter is dan toegestaan door uw platform, is dit de enige manier om het probleem op te lossen. Er zijn stapsgewijze instructies op interneten het zou een eenvoudige operatie moeten zijn voor iemand met enige CS-opleiding. Als je daar problemen mee hebt, plaats dan een nieuwe vraag zodat we je kunnen helpen.


Antwoord 2, autoriteit 21%

Ik heb de recursie gewijzigd in iteratie.

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

Werkt goed 😀


Antwoord 3, autoriteit 14%

De fout is een stack-overflow. Dat zou toch een belletje moeten doen rinkelen op deze site? Dit gebeurt omdat een aanroep naar poruszanieresulteert in een andere aanroep naar poruszanie, waarbij de recursiediepte met 1 wordt verhoogd. De tweede aanroep resulteert in een andere aanroep van dezelfde functie. Dat gebeurt keer op keer, elke keer dat de recursiediepte toeneemt.

Nu zijn de bruikbare bronnen van een programma beperkt. Elke functieaanroep neemt een bepaalde hoeveelheid ruimte in beslag bovenop wat de stapel wordt genoemd. Als de maximale stapelhoogte is bereikt, krijg je een stapeloverloopfout.


Antwoord 4, autoriteit 2%

Dat is de fout die je krijgt als een functie te veel recursieve aanroepen naar zichzelf doet. Het kan dit doen omdat het basisscenario nooit wordt gehaald (en daarom vast komt te zitten in een oneindige lus) of gewoon door een groot aantal oproepen naar zichzelf te doen. Je zou de recursieve aanroepen kunnen vervangen door while-lussen.

Other episodes