2009-08-12 11 views
0

J'ai un programme comme suit:Besoin d'ajouter un élément au début d'un itérateur en python

a=reader.next() 
if *some condition holds*: 
    #Do some processing and continue the iteration 
else: 
    #Append the variable a back to the iterator 
    #That is nullify the operation *a=reader.next()* 

Comment puis-je ajouter un élément au début de la iterator? (Ou existe-t-il un moyen plus facile de faire cela?)

EDIT: OK laissez-moi le mettre ainsi. J'ai besoin de l'élément suivant dans un itérateur sans le supprimer. Comment procéder?>?

+0

Vous pouvez soit faire une enveloppe exactement comme je l'ai expliqué dans ma réponse, ou utilisez itertools.tee, laissez-moi modifier ma réponse. –

Répondre

7

Les itérateurs Python, en tant que tels, ont des fonctionnalités très limitées - pas d'ajout ou quelque chose comme ça. Vous devrez envelopper l'itérateur générique dans un wrapper en ajoutant cette fonctionnalité. .: par exemple

class Wrapper(object): 
    def __init__(self, it): 
    self.it = it 
    self.pushedback = [] 
    def __iter__(self): 
    return self 
    def next(self): 
    if self.pushedback: 
     return self.pushedback.pop() 
    else: 
     return self.it.next() 
    def pushback(self, val): 
    self.pushedback.append(val) 

Ceci est Python 2.5 (devrait fonctionner en 2.6 aussi) - de légères variantes conseillées pour 2,6 et obligatoire pour 3.Toute (utiliser next(self.it) au lieu de self.it.next() et de définir __next__ au lieu de next).

Édition: l'OP dit maintenant ce dont il a besoin: "Regarder en avant sans consommer". Emballage est toujours la meilleure option, mais une alternative est:

import itertools 
    ... 
o, peek = itertools.tee(o) 
if isneat(peek.next()): ... 

ce n'avance o (rappelez-vous avancer si et quand vous décidez de ne voulez ;-).

+0

Oui.Cela fonctionnera.Seulement le problème est l'itérateur est assez grand, mais s'il n'y a pas d'autre moyen cela devra faire pour l'instant – Goutham

+1

Pas de souci - l'itérateur est détenu par référence dans le cas de l'emballage, et itertools.tee sera consommez un espace supplémentaire O (K) où K est le nombre d'éléments dont vous avez besoin pour jeter un coup d'œil. Donc, les "grands itérateurs" ne posent aucun problème! –

2

De par leur conception (dans les concepts généraux de développement), les itérateurs sont destinés à être en lecture seule, et toute tentative de les changer se casserait. Alternativement, vous pouvez lire l'itérateur en arrière, et l'ajouter à la fin de l'élément hte (qui est en fait le début :) :)?

0

Ce n'est pas trop proche de ce que vous avez demandé, mais si vous avez le contrôle sur le générateur et que vous n'avez pas besoin de jeter un coup d'œil avant que la valeur ne soit générée, vous pouvez utiliser la méthode generator.send pour dire le générateur de répéter la dernière valeur qu'il a produit:

>>> def a(): 
...  for x in (1,2,3): 
...    rcvd = yield x 
...    if rcvd is not None: 
...      yield x 
... 
>>> gen = a() 
>>> gen.send("just checking") 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: can't send non-None value to a just-started generator 
>>> gen.next() 
1 
>>> gen.send("just checking") 
1 
>>> gen.next() 
2 
>>> gen.next() 
3 
>>> gen.next() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
StopIteration 
Questions connexes