2014-02-17 163 views
48

我想重复两个不同的迭代器,像这样:在Python中,如何迭代一个迭代器,然后迭代另一个迭代器?

file1 = open('file1', 'r') 
file2 = open('file2', 'r') 
for item in one_then_another(file1, file2): 
    print item 

哪,我期望打印文件1的所有行,然后文件2的所有行。

我想要一些通用的,因为迭代器可能不是文件,这只是一个例子。我知道我可以做到这一点:

for item in [file1]+[file2]: 

但这同时读取文件到内存中,我宁愿避免。

+2

对于未来的读者,正如Ashwini在这里所说的,在这个问题中,最好的通用答案是itertools.chain。 –

+0

如果你正在处理文件,**'fileinput' **是唯一真正的解决方案。 – laike9m

回答

88

使用itertools.chain

from itertools import chain 
for line in chain(file1, file2): 
    pass 

fileinput模块也提供了类似的功能:

import fileinput 
for line in fileinput.input(['file1', 'file2']): 
    pass 
17

您也可以通过简单的generator expression做到这一点:

for line in (l for f in (file1, file2) for l in f): 
    # do something with line 

本我的ThOD你可以表达自己指定一些条件

for line in (l for f in (file1, file2) for l in f if 'text' in l): 
    # do something with line which contains 'text' 

上面的例子相当于本发电机与循环:

def genlinewithtext(*files): 
    for file in files: 
     for line in file: 
      if 'text' in line: 
       yield line 

for line in genlinewithtext(file1, file2): 
    # do something with line which contains 'text' 
7

我觉得最Python化的方法来此特定文件的问题是要使用fileinput模块(因为您需要复杂的上下文管理器或使用open进行错误处理),我将从Ashwini的示例开始,但添加了一些内容。首先,最好用U标志为Universal Newlines支持打开(假设你的Python是用它编译的,大部分是),(r是默认模式,但显式比隐式更好)。如果你与其他人一起工作,最好支持他们给你任何格式的文件。

import fileinput 

for line in fileinput.input(['file1', 'file2'], mode='rU'): 
    pass 

这也是可以使用的命令行,因为它会采取sys.argv中[1:如果你这样做:

import fileinput 

for line in fileinput.input(mode='rU'): 
    pass 

而且你会通过在shell这样的文件:

$ python myscript.py file1 file2 
+0

您能否将模式值更正为'rU'。当我使用'Ur'来尝试代码时,解释器会这样抱怨:“ValueError:FileInput打开模式必须是'r','rU','U'和'rb'之一 – kmario23