Il est parfois préférable d'utiliser une pile plutôt que la récursivité pour les générateurs. Il devrait être possible de réécrire une méthode récursive en utilisant une pile et une boucle while.
Voici un exemple d'une méthode récursive qui utilise un rappel et qui peut être réécrite en utilisant la logique de pile :
def parcourir_arbre(rappel):
# Obtenir le nœud racine de quelque part.
racine = obtenir_noeud_racine()
def recursion(noeud):
rappel(noeud)
for enfant in noeud.get('children', []):
recursion(enfant)
recursion(racine)
La méthode ci-dessus parcourt un arbre de nœuds où chaque nœud a un tableau children
qui peut contenir des nœuds enfants. À chaque nœud rencontré, le rappel est émis et le nœud actuel lui est transmis.
La méthode pourrait être utilisée de cette manière, en imprimant une propriété sur chaque nœud.
def rappel(noeud):
print(noeud['id'])
parcourir_arbre(rappel)
Utiliser une pile à la place et écrire la méthode de traversal comme un générateur
# Une alternative basée sur une pile à la méthode traverse_tree ci-dessus.
def iter_noeuds():
pile = [obtenir_noeud_racine()]
while pile:
noeud = pile.pop()
yield noeud
for enfant in reversed(noeud.get('children', [])):
pile.append(enfant)
(Notez que si vous voulez le même ordre de traversal qu'initialement, vous devez inverser l'ordre des enfants car le premier enfant ajouté à la pile sera le dernier à être retiré.)
Maintenant, vous pouvez obtenir le même comportement que traverse_tree
ci-dessus, mais avec un générateur :
for noeud in iter_noeuds():
print(noeud['id'])
Ce n'est pas une solution universelle mais pour certains générateurs, vous pourriez obtenir un bon résultat en substituant le traitement de la pile à la récursivité.