我正在寻找一种反转生成器对象的方法。我知道如何颠倒顺序:
foo = imap(seq.__getitem__, xrange(len(seq)-1, -1, -1))
但是使用生成器作为输入和反向生成器作为输出是否可能出现类似的情况(len(seq) 保持不变,因此可以使用原始序列中的值)?
除了将生成器转换为序列并从中创建迭代器之外,您不能以任何通用方式反转生成器。在计算出较早的项之前,不一定能够知道生成器的较晚的项。
更糟糕的是,在遇到 StopIteration 异常之前,您无法知道生成器是否会遇到 StopIteration 异常,因此无法知道序列中的第一项是什么。
你能做的最好的事情就是编写一个reverse_iterator函数:
def reversed_iterator(iter):
return reversed(list(iter))
编辑:当然,您也可以将其替换为基于 imap 的迭代版本,以保存一个列表创建。
reversed(list(input_generator))
可能是最简单的方法。
如果不首先将所有生成器的值收集到一个序列中,就无法以“相反”顺序获取生成器的值,因为生成第二个项目很可能依赖于已生成的第一个项目。
无论如何,你都必须遍历生成器才能获得第一个项目,所以你不妨列出一个列表。尝试一下
reversed(list(g))
其中
g
是发电机。
reversed(tuple(g))
也可以工作(我没有检查性能是否有显着差异)。
要在没有中间副本的情况下执行此操作,您必须自己编写一个生成器:
enumerate_reversed = lambda l: zip(range(len(l)-1, -1, -1), reversed(l))
或同等程度
def enumerate_reversed(l):
return zip(range(len(l)-1, -1, -1), reversed(l))
查看我的回答这里以获取更多背景信息。
def reverseGenerator(gen):
new = [i for i in gen]
yield new[::-1][0]
new.pop()
yield from reverseGenerator(i for i in new)