在下面的代码中,我假设有两个生成器生成排序的和可比较的值,我想生成一个生成器,从这两个生成器生成“同步”对。我所说的同步是指当它们产生相同的值时从两者中产生,否则只推进“延迟的”值(将它产生的值与None
配对)。你知道吗
from itertools import repeat
def generate_pairs(g1, g2):
try:
n1 = next(g1)
except StopIteration:
yield from zip(repeat(None), g2)
# A
# raise StopIteration
try:
n2 = next(g2)
except StopIteration:
yield from zip(g1, repeat(None))
# A
# raise StopIteration
while True:
if n1 > n2:
yield (None, n2)
try:
n2 = next(g2)
except StopIteration:
yield (n1, None)
yield from zip(g1, repeat(None))
# B
# raise StopIteration
elif n1 < n2:
yield (n1, None)
try:
n1 = next(g1)
except StopIteration:
yield (None, n2)
yield from zip(repeat(None), g2)
# B
# raise StopIteration
else:
yield (n1, n2)
try:
n1 = next(g1)
except StopIteration:
yield from zip(repeat(None), g2)
# C
# raise StopIteration
try:
n2 = next(g2)
except StopIteration:
yield from zip(g1, repeat(None))
# C
# raise StopIteration
我应该在哪里显式地提出StopIteration
?你知道吗
在上面的状态中,当我尝试使用已经同步的生成器时,我看到在C情况下需要提升。你知道吗
pairs = generate_pairs((n1 for n1 in [1, 2, 3]), (n2 for n2 in [1, 2, 3]))
以上可以继续产生最后一对(3, 3)
:
from cytoolz import take
list(take(10, pairs))
输出:
[(1, 1),
(2, 2),
(3, 3),
(3, 3),
(3, 3),
(3, 3),
(3, 3),
(3, 3),
(3, 3),
(3, 3)]
在B中,似乎也应该提出一个手册StopIteration
:
pairs = generate_pairs((n1 for n1 in [1, 3]), (n2 for n2 in [1, 2]))
list(take(10, pairs))
输出:
[(1, 1),
(None, 2),
(3, None),
(None, 2),
(3, None),
(None, 2),
(3, None),
(None, 2),
(3, None),
(None, 2)]
从下面的测试来看,在我看来,某种结束发电机的方式也是必要的:
pairs = generate_pairs((_ for _ in []), (n2 for n2 in [1, 2, 3]))
list(take(10, pairs))
输出:
UnboundLocalError Traceback (most recent call last)
<ipython-input-96-61eb4df81d52> in <module>
----> 1 list(take(10, pairs))
<string> in generate_pairs(g1, g2)
UnboundLocalError: local variable 'n1' referenced before assignment
但是,如果取消对代码中所有raise StopIteration
的注释,则需要手动处理生成的异常。例如,它们不会在for循环中自动处理。你知道吗
我只希望我的成对生成器在两个输入生成器都用完之后停止生成东西,而不需要戏剧化。我做错什么了?你知道吗
似乎使用return
而不是raise StopIteration
很好地修复了我的代码。不过,我还是对一些解释感兴趣。你知道吗
目前没有回答
相关问题 更多 >
编程相关推荐