Chr*_*ian 2 python yield generator python-3.x
如果我做:
def foo():
yield from range(0,10)
yield from range(10,20)
for num in foo():
print(num)
Run Code Online (Sandbox Code Playgroud)
我得到一个从0到19的有序列表.如果没有更改范围函数的输入,是否有一种简单的方法来指定我想要一个列表:0,10,1,11,2,12 ......
基本上我首先想要每个发生器的第一个元素.比我想要每个发生器的第二个元素然后第三个,依此类推.
奖励点:有没有办法改变它,以便当发电机产生不等量的结果时,第二个发电机在第一个发电机完成后产生剩余的结果?
你正在尝试zip()你的迭代器; 明确地这样做:
from itertools import chain
def foo():
yield from chain.from_iterable(zip(range(10), range(10, 20)))
Run Code Online (Sandbox Code Playgroud)
使用itertools.chain.from_iterable()让你继续在yield from这里使用,扁平化元组zip()产生.
演示:
>>> from itertools import chain
>>> def foo():
... yield from chain.from_iterable(zip(range(10), range(10, 20)))
...
>>> list(foo())
[0, 10, 1, 11, 2, 12, 3, 13, 4, 14, 5, 15, 6, 16, 7, 17, 8, 18, 9, 19]
Run Code Online (Sandbox Code Playgroud)
如果你有不同长度的发电机,你可以使用itertools.zip_longest():
from itertools import zip_longest
def foo():
yield from (i for pair in zip_longest(range(10), range(10, 22))
for i in pair if i is not None)
Run Code Online (Sandbox Code Playgroud)
我在这里使用了不同的展平技术,在生成器表达式中使用了双循环.
这一切都变得乏味,并且因为你没有使用yield from另一个生成器(所以你不需要支持generator.send()和generator.throw()传播),你也可以让它成为一个合适的循环:
def foo():
for x, y in zip_longest(range(10), range(10, 22)):
if x is not None:
yield x
if y is not None:
yield y
Run Code Online (Sandbox Code Playgroud)
您还可以使用文档收件人部分中roundrobin()列出的配方:itertools
from itertools import cycle
def roundrobin(*iterables):
"roundrobin('ABC', 'D', 'EF') --> A D E B F C"
# Recipe credited to George Sakkis
pending = len(iterables)
nexts = cycle(iter(it).__next__ for it in iterables)
while pending:
try:
for next in nexts:
yield next()
except StopIteration:
pending -= 1
nexts = cycle(islice(nexts, pending))
def foo():
yield from roundrobin(range(10), range(10, 22))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
113 次 |
| 最近记录: |