2014-02-17 3 views
48

Я хотел бы повторять два различных итераторы, что-то вроде этого:В Python, как мне перебирать один итератор, а затем другой?

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

Что я бы ожидать, чтобы напечатать все строки file1, то все линии file2.

Мне бы хотелось что-то общее, так как итераторы могут быть не файлами, это всего лишь пример. Я знаю, что смогу это сделать:

for item in [file1]+[file2]: 

но это считывает оба файла в память, которые я бы предпочел избежать.

+2

Для будущих читателей лучшим общим ответом, запрошенным в этом вопросе, является 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

Я думаю, что наиболее Pythonic подход к этой конкретной проблемы файла заключается в использовании модуля fileinput (так как вам нужны сложные диспетчера контекстов или обработка ошибок с помощью open), я собираюсь начать с примера Ашвини, но добавьте несколько вещей. Во-первых, лучше открыть флаг 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 

И вы бы передать файлы в оболочке, как это:

$ python myscript.py file1 file2 
+0

Можете ли вы изменить значение режима на 'rU'. Когда я попробовал код с «Ur», интерпретатор жалуется так: «Режим открытия ValueError: FileInput должен быть одним из« r »,« rU »,« U »и« rb » – kmario23

Смежные вопросы