Как присоединиться к двум генераторам в Python?

Я хочу изменить следующий код

for directory, dirs, files in os.walk(directory_1):
    do_something()

for directory, dirs, files in os.walk(directory_2):
    do_something()

к этому коду:

for directory, dirs, files in os.walk(directory_1) + os.walk(directory_2):
    do_something()

Я получаю сообщение об ошибке:

неподдерживаемый тип (-ы) операндов для +: 'генератор' и 'генератор'

Как присоединиться к двум генераторам в Python?

Ответ 2

Пример кода:

from itertools import chain

def generator1():
    for item in 'abcdef':
        yield item

def generator2():
    for item in '123456':
        yield item

generator3 = chain(generator1(), generator2())
for item in generator3:
    print item

Ответ 3

Простой пример:

from itertools import chain
x = iter([1,2,3])      #Create Generator Object (listiterator)
y = iter([3,4,5])      #another one
result = chain(x, y)   #Chained x and y

Ответ 4

В Python (3.5 или выше) вы можете сделать:

def concat(a, b):
    yield from a
    yield from b

Ответ 5

С помощью itertools.chain.from_iterable вы можете делать такие вещи, как:

def genny(start):
  for x in range(start, start+3):
    yield x

y = [1, 2]
ab = [o for o in itertools.chain.from_iterable(genny(x) for x in y)]
print(ab)

Ответ 6

Здесь используется генераторное выражение с вложенными for s:

a = range(3)
b = range(5)
ab = (i for it in (a, b) for i in it)
assert list(ab) == [0, 1, 2, 0, 1, 2, 3, 4]

Ответ 7

Если вы хотите, чтобы генераторы разделяли, но все же повторяли их, вы можете использовать zip():

ПРИМЕЧАНИЕ. Итерация останавливается на более коротком из двух генераторов

Например:

for (root1, dir1, files1), (root2, dir2, files2) in zip(os.walk(path1), os.walk(path2)):

    for file in files1:
        #do something with first list of files

    for file in files2:
        #do something with second list of files

Ответ 8

Предположим, что мы имеем генераторы (gen1 и gen 2), и мы хотим выполнить некоторый дополнительный расчет, который требует результата обоих. Мы можем вернуть результат такой функции/вычисления с помощью метода карты, который, в свою очередь, возвращает генератор, на который мы можем контактировать.

В этом случае функция/вычисление необходимо реализовать с помощью лямбда-функции. Сложная часть - это то, что мы стремимся делать внутри карты и ее лямбда-функции.

Общая форма предлагаемого решения:

def function(gen1,gen2):
        for item in map(lambda x, y: do_somethin(x,y), gen1, gen2):
            yield item

Ответ 9

Можно также использовать оператор распаковки *:

concat = (*gen1(), *gen2())

ПРИМЕЧАНИЕ. Наиболее эффективно работает для "не ленивых" итераций. Может также использоваться с различными видами понимания. Предпочтительный способ для генератора concat будет из ответа от @Uduse

Ответ 10

Все эти сложные решения...

просто сделайте:

for dir in director_1, directory_2:
    for directory, dirs, files in os.walk(dir):
        do_something()

Если вы действительно хотите "присоединиться" к обоим генераторам, выполните:

for directory, dirs, files in 
        [x for osw in [os.walk(director_1), os.walk(director_2)] 
               for x in osw]:
    do_something()