web-dev-qa-db-fra.com

Récursion en Python? RuntimeError: profondeur maximale de récursivité dépassée lors de l'appel d'un objet Python

Dupliquer possible:
Profondeur maximale de récursivité?

J'ai un autre problème avec mon code. J'écris mon premier programme sous Vpython et je dois simuler le mélange de deux gaz. D'abord, j'ai eu un problème avec les frontières, mais maintenant, quand les balles (qui représentent les particules de gaz) restent dans les frontières, il y a différentes choses qui ne vont pas. Après quelques secondes, j'obtiens une erreur, qui est indiquée sous le code source de ma fonction. 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

l'erreur est:

    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

Quelqu'un peut-il penser à un moyen de simplifier ma fonction?

Je lance la fonction en boucle:

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)
8
Emil Smęt

Python ne dispose pas des optimisations de récursion de queue communes dans les langages fonctionnels tels que LISP. En Python, la récursivité est limitée à 999 appels (voir sys.getrecursionlimit ).

Si la profondeur 999 est supérieure à vos attentes, vérifiez si la mise en œuvre ne contient pas de condition qui arrête la récursivité, ou si ce test peut être incorrect dans certains cas.

J'ose dire qu'en Python, les implémentations d'algorithmes purement récursifs ne sont pas correctes/sûres. Une implémentation fib () limitée à 999 n'est pas vraiment correcte. Il est toujours possible de convertir récursif en itératif, ce qui est trivial. 

Il n'est pas souvent atteint car dans de nombreux algorithmes récursifs, la profondeur a tendance à être logarithmique. Si ce n'est pas le cas avec votre algorithme sont susceptibles d'obtenir des appels récursifs de plus de 999, vous avez deux options:

1) Vous pouvez modifier la limite de récursion avec sys.setrecursionlimit(n) jusqu'au maximum autorisé pour votre plate-forme:

sys.setrecursionlimit(limit)

Définissez la profondeur maximale de la pile d'interpréteur Python à limiter. Cette limite empêche la récursion infinie de provoquer un débordement de la pile C et un crash de Python.

La limite la plus élevée possible dépend de la plate-forme. Un utilisateur peut avoir besoin de définir une limite supérieure quand il dispose d'un programme nécessitant une récursion profonde et d'une plate-forme prenant en charge une limite supérieure. Cela doit être fait avec précaution, car une limite trop élevée peut entraîner un crash.

2) Vous pouvez convertir pour convertir l'algorithme de récursif en itératif. Si la profondeur de récursivité est supérieure à celle autorisée par votre plate-forme, c'est le seul moyen de résoudre le problème. Si cela vous pose problème, posez une nouvelle question pour que nous puissions vous aider.

25
Paulo Scardine

J'ai changé la récursion à l'itération. 

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

Fonctionne bien: D

5
Emil Smęt

L'erreur est un débordement de pile. Cela devrait vous rappeler quelque chose sur ce site, non? Cela se produit car un appel à poruszanie entraîne un autre appel à poruszanie, incrémentant la profondeur de la récursivité de 1. Le deuxième appel entraîne un autre appel de la même fonction. Cela se produit encore et encore, à chaque fois en augmentant la profondeur de récursivité.

Maintenant, les ressources utilisables d'un programme sont limitées. Chaque appel de fonction occupe une certaine quantité d’espace au-dessus de ce que l’on appelle la pile. Si la hauteur maximale de la pile est atteinte, vous obtenez une erreur de débordement de la pile.

4
pvoosten

C'est l'erreur que vous obtenez quand une fonction fait trop d'appels récursifs à elle-même. Cela peut être dû au fait que le scénario de base n’est jamais respecté (et qu’il se bloque donc dans une boucle infinie) ou simplement en effectuant un grand nombre d’appels. Vous pouvez remplacer les appels récursifs par des boucles while.

0
mojzu