我想更改下面的代码

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()

我得到了错误:

不支持+:'generator'和'generator'的操作数类型

如何在Python中连接两个生成器?


当前回答

代码示例:

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

其他回答

这里使用了一个带有嵌套for的生成器表达式:

range_a = range(3)
range_b = range(5)
result = (item
    for one_range in (range_a, range_b)
    for item in one_range)
assert list(result) == [0, 1, 2, 0, 1, 2, 3, 4]

for…在…从左到右求值。for之后的标识符建立一个新变量。而one_range在下面用于…在…,来自第二个的项用于“final”赋值表达式,该表达式只有一个(在最开始)。

Itertools.chain()应该做到这一点。它接受多个可迭代对象,并逐个产生结果,大致相当于:

def chain(*iterables):
    for it in iterables:
        for element in it:
            yield element

使用的例子:

from itertools import chain

g = (c for c in 'ABC')  # Dummy generator, just for example
c = chain(g, 'DEF')  # Chain the generator and a string
for item in c:
    print(item)

输出:

A
B
C
D
E
F

您可以将任何生成器放入列表中。虽然不能组合生成器,但可以组合列表。这样做的缺点是实际上在内存中创建了3个列表,但优点是可读性非常好,不需要导入,并且是单行习惯用法。

OP解决方案。

for directory, dirs, files in list(os.walk(directory_1)) + list(os.walk(directory_2)):
    do_something()
a = range(20)
b = range(10,99,3)
for v in list(a) + list(b):
    print(v) 

在Python(3.5或更高版本)中,您可以执行以下操作:

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

我想说的是,正如用户“wjandrea”的评论所建议的那样,最好的解决方案是

def concat_generators(*gens):
    for gen in gens:
        yield from gen

它不会改变返回的类型,并且是真正的python类型。