一次读2行

时间:2009-10-06 23:42:03

标签: python

有没有更好的方法从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 个答案:

答案 0 :(得分: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_longest)。

答案 1 :(得分: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

答案 2 :(得分:1)

适用于中小型文件,

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