当您使用f.next()遍历文件时,Python的f.tell无法正常工作:
>>> f=open(".bash_profile", "r") >>> f.tell() 0 >>> f.next() "alias rm='rm -i'\n" >>> f.tell() 397 >>> f.next() "alias cp='cp -i'\n" >>> f.tell() 397 >>> f.next() "alias mv='mv -i'\n" >>> f.tell() 397
看起来它为您提供了缓冲区的位置,而不是您通过next()获得的位置。
以前,我在使用readline()遍历文件时曾使用过seek / tell技巧来倒退一行。使用next()时是否有一种方法可以快退一行?
否。我将创建一个适配器,该适配器在很大程度上转发所有呼叫,但在执行时保留最后一行的副本,next然后让您调用其他方法以使该行再次弹出。
next
实际上,我将适配器做成可以包装任何可迭代对象的适配器,而不是文件包装器,因为这听起来像在其他情况下经常有用。
亚历克斯建议使用itertools.tee适配器也可以,但是我认为编写自己的迭代器适配器来处理这种情况通常会更干净。
itertools.tee
这是一个例子:
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()
扩展到允许您以不止一个值进行备份的方式并不难。