No. Yo haría un adaptador que gran parte reenvía todas las llamadas, pero mantuvo una copia de la última línea cuando lo hizo y luego next
le permite llamar a un método diferente para hacer que esa línea salga de nuevo.
De hecho, haría que el adaptador sea un adaptador que podría envolver cualquier iterable en lugar de un contenedor para el archivo porque parece que sería útil en otros contextos.
La sugerencia de Alex de usar el adaptador itertools.tee
también funciona, pero creo que escribir su propio adaptador de iterador para manejar este caso en general sería más limpio.
Aquí se muestra un ejemplo:
class rewindable_iterator(object):
not_started = object()
def __init__(self, iterator):
self._iter = iter(iterator)
self._use_save = False
self._save = self.not_started
def __iter__(self):
return self
def next(self):
if self._use_save:
self._use_save = False
else:
self._save = self._iter.next()
return self._save
def backup(self):
if self._use_save:
raise RuntimeError("Tried to backup more than one step.")
elif self._save is self.not_started:
raise RuntimeError("Can't backup past the beginning.")
self._use_save = True
fiter = rewindable_iterator(file('file.txt', 'r'))
for line in fiter:
result = process_line(line)
if result is DoOver:
fiter.backup()
Esto no sería demasiado duro para extender en algo que permite hacer copias de seguridad en más de un solo valor.
Esta es la mejor solución para mí. Ya tenía algo así como un envoltorio, así que fue fácil modificarlo de esta manera. –
Actualización para python3: use '__next__' en lugar de next y este ejemplo funcionará. Consulte http://getpython3.com/diveintopython3/porting-code-to-python-3-with-2to3.html#next –