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

Hom*_*ing 158 python generator

我想更改以下代码

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

for directory, dirs, files in os.walk(directory_2):
    do_something()
Run Code Online (Sandbox Code Playgroud)

这段代码:

for directory, dirs, files in os.walk(directory_1) + os.walk(directory_2):
    do_something()
Run Code Online (Sandbox Code Playgroud)

我收到错误:

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

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

Phi*_*ipp 208

我认为itertools.chain()应该这样做.

  • 你为什么不写一个可行的例子呢? (4认同)
  • 应该记住的是,“ itertools.chain()”的返回值不会返回“ types.GeneratorType”实例。以防万一,确切的类型至关重要。 (2认同)
  • @yash你可能喜欢[zip](https://docs.python.org/3/library/functions.html#zip)。它正是这样做的,挑选出第一个、第二个等值并将它们放入元组中。 (2认同)

小智 56

代码示例:

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
Run Code Online (Sandbox Code Playgroud)

  • 为什么不将这个例子添加到已经存在的,高度赞成的`itertools.chain()`答案中? (8认同)
  • 嗯。因为这会让他损失 850 代表。这家伙有 851。你做你的,cesio。 (3认同)
  • @Jean-FrançoisCorbett 写下“已经存在”答案的人真的可以做到这一点......好吗?:) (2认同)

use*_*754 26

简单的例子:

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
Run Code Online (Sandbox Code Playgroud)

  • 为什么不将这个示例添加到已经存在的,高度评价的`itertools.chain()`答案中呢? (2认同)

Udu*_*use 26

在Python(3.5或更高版本)中,您可以:

def concat(a, b):
    yield from a
    yield from b
Run Code Online (Sandbox Code Playgroud)

  • 更一般的:`def chain(* iterables):对于可迭代对象中的可迭代对象:可迭代对象的收益(在运行时将`def`和`for`放在单独的行上。) (5认同)
  • 这么多pythonic。 (4认同)
  • @问题官员 是的。即使“b”不是迭代器,也只会检查“a”,直到从中产生所有内容。稍后会出现“b”不是迭代器的“TypeError”。 (4认同)
  • 是 *a* 中的所有内容先于 *b* 中的任何内容产生,还是它们正在交替? (2认同)

and*_*ate 9

使用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)
Run Code Online (Sandbox Code Playgroud)


use*_*461 8

2020 更新:可在 Python 3 和 Python 2 中工作

import itertools

iterA = range(10,15)
iterB = range(15,20)
iterC = range(20,25)
Run Code Online (Sandbox Code Playgroud)

第一个选择

for i in itertools.chain(iterA, iterB, iterC):
    print(i)

# 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
Run Code Online (Sandbox Code Playgroud)

替代选项,在 python 2.6 中引入

for i in itertools.chain.from_iterable( [iterA, iterB, iterC] ):
    print(i)

# 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
Run Code Online (Sandbox Code Playgroud)

itertools.chain()是基础。

如果你有一个可迭代的可迭代对象,itertools.chain.from_iterable()会很方便。例如每个子目录的文件列表,例如[ ["src/server.py", "src/readme.txt"], ["test/test.py"] ].


Ale*_*xey 5

在这里,它使用带有s 的生成器表达式for

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]
Run Code Online (Sandbox Code Playgroud)

  • 稍加解释就不会受伤。 (2认同)

sol*_*l25 5

还可以使用解包运算符*

concat = (*gen1(), *gen2())
Run Code Online (Sandbox Code Playgroud)

注意:对于“非惰性”迭代最有效。也可以用于不同类型的理解。生成器连接的首选方式来自@Uduse

  • –1 这将立即将两个生成器消耗成一个元组! (3认同)