我最近编写了这个python3代码,它应该在所有提供给它的iterables之间交替使用。也就是说,如果函数作为参数(first, second, third)
给出,那么它将产生first[0], second[0], third[0], first[1], ...
。如果second
在其他项之前用完,则跳过它:second[15], third[16], first[16], third[16], ...
,直到所有iterables都用完为止。你知道吗
给你。它是功能性的,但它看起来不是很“Python”。我特别不喜欢保留一系列的标志来告诉我发电机是空的。你知道吗
def zipper(*many):
iterators = [iter(x) for x in many]
iHasItems = [True]*len(iterators)
while any(iHasItems):
for n, iterator in enumerate(iterators):
if iHasItems[n]:
try:
yield next(iterator)
except StopIteration:
iHasItems[n] = False
您基本上是在重新实现itertools文档recipes section中记录的
roundrobin()
函数:每次引发
StopIteration
异常时,它循环遍历迭代器并切掉最后一个迭代器;最后一个迭代器总是刚刚耗尽的迭代器。你知道吗具体地说,对于输入示例,
nexts
以这些位置的<iter('ABC'), iter('D'), iter('EF')>
的循环列表开始,并且num_active
是3
,然后算法进行:A
并离开<iter('D'), iter('EF'), iter('BC')>
D
并离开<iter('EF'), iter('BC'), <iter('')>
E
并离开<iter('BC'), <iter(''), iter('F')>
B
并离开<iter(''), iter('F'), iter('C')>
StopIteration
异常;然后循环在<iter('F'), iter('C'), iter(*stopped*)>
,因此num_active
变成2
,cycle(islice(nexts, 2))
将循环设置为<iter('F'), iter('C')>
,while
循环继续F
并离开<iter('C'), iter('')>
C
并离开<iter(''), iter('')>
之后,最后两个空迭代器会触发更多
StopIteration
异常,num_active
从2变为1变为0,while
循环结束。你知道吗您可以使用
collections.deque()
对象和手动旋转实现相同的功能:但是这种方法比
cycle
变体慢,因为循环是“手动”完成的,每次迭代都会产生成本,超过了简单的“耗尽”异常情况实现。你知道吗与您的方法一样,这样可以避免重复尝试迭代任何已经用尽的迭代器,并且与其他人发布的
zip_longest()
方法不同,不需要您在每次迭代中测试sentinel值(item is not None
或not item
或item is not unique_sentinel_singleton
)。你知道吗将
iterables
和chain
压缩到一起相关问题 更多 >
编程相关推荐