【问题标题】:reading lines 2 at a time一次读取 2 行
【发布时间】:2009-10-06 23:42:02
【问题描述】:

有没有比在 python 文件中一次读取两行更好的方法:

with open(fn) as f:
    for line in f:
        try:
            line2 = f.next()
        except StopIteration:
            line2 = ''
        print line, line2 # or something more interesting

我在 2.5.4。新版本有什么不同吗?

编辑:已删除的答案指出:在 py3k 中,您需要执行 next(f) 而不是 f.next()。更不用说印刷变化了

【问题讨论】:

    标签: python


    【解决方案1】:
    import itertools
    
    with open(fn) as f:
      for line, line2 in itertools.izip_longest(f, f, fillvalue=''):
        print line, line2
    

    唉,izip_longest 需要 Python 2.6 或更高版本; 2.5 只有izip,如果f 有奇数行,它会截断最后一行。当然,提供与生成器相同的功能非常容易。

    这是一个更通用的“一次 N 个”迭代器包装器:

    def natatime(itr, fillvalue=None, n=2):
      return itertools.izip_longest(*(iter(itr),)*n, fillvalue=fillvalue)
    

    itertools 通常是最好的方法,但是,如果你坚持自己实现,那么:

    def natatime_no_itertools(itr, fillvalue=None, n=2):
      x = iter(itr)
      for item in x:
        yield (item,) + tuple(next(x, fillvalue) for _ in xrange(n-1))
    

    在 2.5 中,我认为最好的方法其实不是生成器,而是另一种基于 itertools 的解决方案:

    def natatime_25(itr, fillvalue=None, n=2):
      x = itertools.chain(iter(itr), (fillvalue,) * (n-1))
      return itertools.izip(*(x,)*n)
    

    (因为2.5没有内置next,也没有izip_longest)。

    【讨论】:

    • 从来没有关注过nextdefault参数,谢谢指出。
    • try/except 看起来简单明了(如果我们可以保证偶数行就不需要了)。为什么你更喜欢在这里写一个生成器?生成器不需要 try/except 吗?
    • 除非我删除最后一个参数,(空字符串)我得到 ValueError: too many values to unpack。你想用它来完成什么?
    • @foosion,我明白你的意思,但我认为这真的归结为熟悉——你熟悉循环文件,“知道”文件是它自己的迭代器,所以调用接下来“推进”它(所以for 不会再读那一行),了解 StopIteration 等;而且您对 itertools 并不熟悉,因此您发现它不那么直接……但本质上并非如此,就像一个同样熟悉两组概念并将它们教给不熟悉任何一个的有经验的程序员的人一样。不过,当然,不管你的船是什么!-)
    • @Alex - 我完全同意。事情从“什么??”开始。当一个人变得更有经验时,“哦,这很有意义”到“当然”。可读性很好,但扩展可读性更好。
    【解决方案2】:

    您可以使用生成器使其更清晰:

    def read2(f):
        for line in f:
            try:
                line2 = f.next()
            except StopIteration:
                line2 = ''
    
            yield line, line2
    
    with open(fn) as f:
        for line1, line2 in read2(f):
            print line1
            print line2
    

    【讨论】:

      【解决方案3】:

      对于中小型文件,

      >>> data=open("file").readlines()
      >>> for num,line in enumerate(data[::2]):
      ...  print ''.join(data[num:num+2])
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-09-18
        • 2014-12-01
        • 1970-01-01
        • 2017-06-24
        • 2011-01-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多