一次读取两行

14 投票
3 回答
4150 浏览
提问于 2025-04-15 14:52

有没有比下面这种方法更好的方式来每次从文件中读取两行内容呢?

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版本。新版本有什么不同吗?

补充说明:有个被删除的回答提到,在Python 3中,你需要用next(f)来代替f.next()。还有打印方式也有变化。

3 个回答

1

对于小到中等大小的文件,

>>> data=open("file").readlines()
>>> for num,line in enumerate(data[::2]):
...  print ''.join(data[num:num+2])
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
18
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)。

撰写回答