2009-08-12 1 views
0

ich ein Programm haben, wie folgt hinzufügen:Benötigen Sie ein Element am Anfang eines Iterators in 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()* 

Wie füge ich ein Element zu Beginn des Iterator? (Oder gibt es einen einfacheren Weg, dies zu tun?)

EDIT: OK, lassen Sie mich es so sagen. Ich brauche das nächste Element in einem Iterator, ohne es zu entfernen. Wie mache ich das>?

+0

Sie entweder tun einen Wrapper genau so, wie ich erklärte in meiner Antwort, oder verwenden Sie itertools.tee, lassen Sie mich meine Antwort bearbeiten. –

Antwort

7

Python-Iteratoren haben als solche eine sehr eingeschränkte Funktionalität - kein "Anhängen" oder Ähnliches. Sie müssen den generischen Iterator in einen Wrapper umbrechen, der diese Funktionalität hinzufügt. Z.B .:

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) 

Dies ist Python 2.5 (sollte auch in 2.6 funktionieren) - leichte Varianten für 2,6 und verpflichtend für 3.any empfohlen (verwenden next(self.it) statt self.it.next() und definieren __next__ statt next).

Bearbeiten: das OP sagt jetzt, was sie brauchen, ist "Vorschau ohne zu verbrauchen". Wrapping ist immer noch die beste Wahl, aber eine Alternative:

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

dies nicht o (erinnert sich voran es vorzurücken, ob und wann Sie sich entscheiden, was Sie tun wollen ;-).

+0

Yes.This wird funktionieren.Nur Problem ist der Iterator ist ziemlich groß, aber wenn es keine andere Möglichkeit gibt, wird dies für jetzt tun müssen – Goutham

+1

Keine Sorge - der Iterator wird durch Referenz im Wrapper-Fall gehalten, und itertools.tee wird verbrauchen Sie zusätzlichen Speicherplatz O (K) wobei K die Anzahl der Elemente ist, die Sie voraussehen müssen. So sind "große Iteratoren" kein Problem! –

2

Durch Design (in allgemeinen Entwicklungskonzepten) sollen Iteratoren schreibgeschützt sein, und jeder Versuch, sie zu ändern, würde brechen.

Alternativ könnten Sie den Iterator rückwärts lesen, und fügen Sie es am Ende des Elements (was ist eigentlich der Start :))?

0

Dies ist nicht zu nahe, was Sie gefragt haben, aber wenn Sie die Kontrolle über den Generator haben und Sie müssen nicht "Peek", bevor der Wert generiert wird (und irgendwelche Nebenwirkungen aufgetreten sind), können Sie verwenden die generator.send Verfahren um den Generator zu sagen, den letzten Wert, der es ergab zu wiederholen:

>>> 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