2 votes

Besoin d'aide pour comprendre le fonctionnement de cette fonction récursive

Voici une fonction (merci à l'utilisateur Abbot, qui l'a fournie dans une autre question)

def traverse(ftp):

    level = {}
    for entry in (path for path in ftp.nlst() if path not in ('.', '..')):
        ftp.cwd(entry)
        level[entry] = traverse(ftp) 
        ftp.cwd('..')
    return level

Voici ce que je ne comprends pas : Lorsque python entre dans la fonction, il crée un dictionnaire vide ( level ). Dans la boucle for, il stocke un nom de répertoire comme clé dans le dictionnaire. Pour ce qui est de la valeur de cette clé, Python entre à nouveau dans la fonction et recherche un répertoire qui devient la valeur de cette clé.

Mais comment le dictionnaire de niveau se souvient-il des valeurs qu'il contient ? Je veux dire, ne devrait-il pas être réinitialisé/vidé à chaque fois que Python entre dans la fonction ?

7voto

badp Points 5036

Non. Chaque "instance" de la fonction possède sa propre copie de level et il n'y a pas d'effets secondaires entre les différentes copies du level .

Prenons l'exemple de cet arbre à dossiers :

root
 `-home
    |- lyrae
    |   |- ftp.py
    |   `- http.py
    `- badp

Voici le flux d'exécution (simplifié) lorsque vous appelez ftp sur root :

  • ftp(root) crée un espace vide level dictionnaire
  • ftp(root) énumère les sous-dossiers : (home) .
  • ftp(root) choisit le premier sous-dossier et y change de répertoire.
  • ftp(root) ensembles level[home] au résultat de ftp dans le dossier en cours.

  • ftp(home) crée un espace vide level dictionnaire
  • ftp(home) énumère les sous-dossiers : (lyrae, badp) .
  • ftp(home) choisit le premier sous-dossier et y change de répertoire.
  • ftp(home) ensembles level[lyrae] au résultat de ftp dans le dossier en cours.

  • ftp(lyrae) crée un espace vide level dictionnaire
  • ftp(lyrae) énumère les sous-dossiers : () .
  • ftp(lyrae) n'a plus de sous-dossiers à analyser et renvoie level .

  • ftp(home) complète la mission : levels = {'lyrae': {}}
  • ftp(home) passe au dossier suivant.
  • ftp(home) ensembles level[badp] au résultat de ftp dans le dossier en cours.

  • ftp(badp) crée un espace vide level dictionnaire
  • ftp(badp) énumère les sous-dossiers : () .
  • ftp(badp) n'a plus de sous-dossiers à analyser et renvoie level .

  • ftp(home) complète la mission : levels = {'lyrae': {}, 'badp': {}}
  • ftp(home) n'a plus de sous-dossiers à analyser et renvoie level .

  • ftp(root) complète la mission : levels = {'home': {'lyrae': {}, 'badp': {}}}
  • ftp(root) n'a plus de sous-dossiers à analyser et renvoie level .

2voto

Benj Points 12084

Je pense que les autres réponses n'expliquent pas suffisamment les choses. Chaque entrée récursive dans cette fonction crée un nouveau dictionnaire au niveau local. Mais surtout, elle le renvoie. Cela signifie que la version locale du niveau de chaque récursivité devient un dictionnaire arborescent de niveaux. Une fois la récursivité déroulée, vous vous retrouvez avec un arbre de dictionnaires qui se réfèrent les uns aux autres. Cela signifie que les variables locales qui sont créées ne sont pas ramassées parce qu'il y a une référence au dictionnaire du niveau le plus élevé sur la pile qui a été renvoyée par la fonction la plus éloignée.

1voto

Amnon Points 4864

level est une variable locale. Chaque "exécution" de la fonction possède sa propre variable appelée level afin que les variables n'interfèrent pas entre elles.

1voto

cjrh Points 3960

Le champ d'application de la level est limité à la fonction. Même si une fonction s'appelle elle-même, cela ne veut pas dire que que les variables internes de l'appel de fonction (a différents level ) est identique à este de l'un d'entre eux.

1voto

SilentGhost Points 79627

Variable level n'existe que dans la portée d'une fonction, à la fin de la fonction les variables locales sont éliminées, donc pour chaque exécution de traverse il y aura sa propre level dictionnaire. Rien ne sera réécrit ou surécrit.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X