代码之家  ›  专栏  ›  技术社区  ›  foosion

一次阅读第2行

  •  12
  • foosion  · 技术社区  · 17 年前

    是否有比以下更好的方法从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中,你需要做下一步(f),而不是f.next()。更不用说打印更改了

    3 回复  |  直到 17 年前
        1
  •  17
  •   Alex Martelli    17 年前
    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-最长 )

        2
  •  2
  •   six8    17 年前

    你可以用发电机更清楚地说明:

    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
  •  1
  •   ghostdog74    17 年前

    对于中小型文件,

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