2010-12-16 3 views
2

J'ai écrit une classe d'arbres en Python, mais j'avoir des problèmes en créant dans iterator pour elle je veux être en mesure de faireITERATE (dans un arbre Python)

phonebook = MyTree() 
# Build up tree 

for node in phonebook: 
    print "%s: %s" % (node.key(), node.data()) 

Mais cela ne fonctionne pas (dit que l'objet générateur n'a pas de clé() et de donnée()). La fonction __iter__ de ma classe Tree retourne une classe d'itérateur que j'ai créée. Voici ce que j'ai jusqu'ici (je sais que c'est faux et ça ne marche pas car il retourne un objet générateur, puisque c'est ce que fait le rendement, je veux qu'il se souvienne où il était dans la récursivité ... donc je ne peux pas utiliser return) . Fondamentalement, je veux juste retourner les nœuds en ordre.

class TreeIterator(): 
    def __init__(self, root, size): 
     self._current = root 
     self._size = size 
     self.num_visited = 0 

    def __iter__(self): 
     return self 

    def next(self): 
     return self._next(self._current) 

    def _next(self, curr): 
     self.num_visited = self.num_visited + 1 
     if self.num_visited == self._size: 
      raise StopIteration 

     if curr.left is not None and curr.left is not TreeNode.NULL: 
      yield self._next(curr.left) 

     yield curr 

     if curr.right is not None and curr.right is not TreeNode.NULL: 
      yield self._next(curr.right) 

Répondre

2

Essayez de changer

if curr.left is not None and curr.left is not TreeNode.NULL: 
    yield self._next(curr.left) 

yield curr 

if curr.right is not None and curr.right is not TreeNode.NULL: 
    yield self._next(curr.right) 

dans

if curr.left is not None and curr.left is not TreeNode.NULL: 
    for x in self._next(curr.left): 
     yield x 

yield curr 

if curr.right is not None and curr.right is not TreeNode.NULL: 
    for x in self._next(curr.right): 
     yield x 

On dirait que vous êtes yield ing un itérateur, pas une valeur. Je pense aussi que votre approche générale est trop compliquée.

self._next(curr.left) renvoie un générateur/un itérateur. Il contient un tas de valeurs, pas seulement une, de sorte que vous devez faire une boucle.

+0

Cela a fonctionné, j'ai déjà vu cela avant mais je ne pouvais pas le faire fonctionner alors. Pouvez-vous expliquer pourquoi cela fonctionne? Je ne comprends toujours pas x pour self_next (curr.left). – robev

1

Votre fonction TreeIterator._next() est une fonction de générateur. Cela signifie qu'il renvoie un itérateur lors de son appel. Vous pouvez donc stocker la valeur de retour de _next() et appeler le .next() sur cette valeur de retour pour obtenir les éléments successifs de cet itérateur. Ce que vous faites d'autre part est toujours retourner un nouvellement créé itérateur dans TreeIterator.next(), qui n'est jamais itératie terminée. Cela explique également le message d'erreur que vous obtenez: Votre itérateur ne renvoie pas d'entrées d'arbre, mais plutôt de nouveaux itérateurs.

Je pense que la solution la plus simple pour ce problème est de supprimer complètement la classe TreeIterator et de copier sa méthode ._next() à la méthode .__iter__() de votre classe d'arbre. Peut-être que certaines choses doivent être corrigées, mais je ne connais pas votre classe d'arbre.

+0

Merci je me suis débarrassé de la classe et tous ses attributs (qui ne sont pas nécessaires). Cependant, cela n'a toujours pas fonctionné, la réponse de robert a réglé le problème principal. – robev

+0

@robev: En fait, les deux étaient des "problèmes principaux". Vous aviez besoin de corriger ces deux bogues pour que ça fonctionne. Mais heureux que nous puissions vous aider :) –

1

On dirait que vous essayez d'itérateur sur le type, pas l'instance du type. Changer ceci:

for node in MyTree: 
    print "%s: %s" % (node.key(), node.data()) 

à:

for node in phonebook: 
    print "%s: %s" % (node.key(), node.data()) 
+0

Désolé que c'était une faute de frappe, je fais # 2 :) – robev