Python 反向生成器

发布于 2024-08-07 13:25:54 字数 187 浏览 6 评论 0原文

我正在寻找一种反转生成器对象的方法。我知道如何反转序列:

foo = imap(seq.__getitem__, xrange(len(seq)-1, -1, -1))

但是使用生成器作为输入和反转生成器作为输出(len(seq) 保持不变,因此可以使用原始序列的值)是否可能发生类似的情况?

I'm looking for a way to reverse a generator object. I know how to reverse sequences:

foo = imap(seq.__getitem__, xrange(len(seq)-1, -1, -1))

But is something similar possible with a generator as the input and a reversed generator as the output (len(seq) stays the same, so the value from the original sequence can be used)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

傲影 2024-08-14 13:25:54

除了将生成器转换为序列并从中创建迭代器之外,您不能以任何通用方式反转生成器。在计算出较早的项之前,不一定能够知道生成器的较晚的项。

更糟糕的是,在遇到 StopIteration 异常之前,您无法知道生成器是否会遇到 StopIteration 异常,因此无法知道序列中的第一项是什么。

你能做的最好的事情就是编写一个reverse_iterator函数:

def reversed_iterator(iter):
    return reversed(list(iter))

编辑:当然,你也可以用基于imap的迭代版本替换reverse,以保存一个列表创建。

You cannot reverse a generator in any generic way except by casting it to a sequence and creating an iterator from that. Later terms of a generator cannot necessarily be known until the earlier ones have been calculated.

Even worse, you can't know if your generator will ever hit a StopIteration exception until you hit it, so there's no way to know what there will even be a first term in your sequence.

The best you could do would be to write a reversed_iterator function:

def reversed_iterator(iter):
    return reversed(list(iter))

EDIT: You could also, of course, replace reversed in this with your imap based iterative version, to save one list creation.

朱染 2024-08-14 13:25:54

reversed(list(input_generator)) 可能是最简单的方法。

如果不先将所有生成器的值收集到一个序列中,就无法以“相反”顺序获取生成器的值,因为生成第二个项目很可能依赖于第一个项目的生成。

reversed(list(input_generator)) is probably the easiest way.

There's no way to get a generator's values in "reverse" order without gathering all of them into a sequence first, because generating the second item could very well rely on the first having been generated.

蝶舞 2024-08-14 13:25:54

无论如何,您都必须遍历生成器才能获得第一个项目,因此您不妨列出一个列表。尝试

reversed(list(g))

其中 g 是生成器。

reversed(tuple(g))

也会起作用(我没有检查性能是否有显着差异)。

You have to walk through the generator anyway to get the first item so you might as well make a list. Try

reversed(list(g))

where g is a generator.

reversed(tuple(g))

would work as well (I didn't check to see if there is a significant difference in performance).

天冷不及心凉 2024-08-14 13:25:54

之前的所有答案都会创建中间副本,从而导致内存使用量大幅增加。

生成器的唯一目的就是避免这种情况。

一般来说,正如其他人所说,不可能反转生成器(因为您必须遍历/迭代整个生成器直到满足停止条件,将输出保存在新创建的对象中并反转该对象/创建一个反转迭代器这个新创建的对象)。

但是,凭借您的特定知识/如果您知道生成器的作用,您有时可以自己编写一个新的、相反的生成器。

例如,要反转普通 enumerate 而无需中间副本,您可以编写:

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))

查看我的答案 这里了解更多背景信息。

All previous answers create intermediate copies that cause large spikes in memory usage.

The sole purpose of a generator is to avoid that.

In general, as others said, it is impossible to reverse a generator (as you have to walk / iterate though the whole generator until the stop condition is met, save the outputs in a newly created object and reverse this object / create an iterator reversing this newly created object).

But with your specific knowledge / if you know, what the generator does, you can sometimes write a new, reverse, one yourself.

For example, to reverse plain enumerate without intermediate copies, you can write:

enumerate_reversed = lambda l: zip(range(len(l)-1, -1, -1), reversed(l))

or equivalently

def enumerate_reversed(l):
    return zip(range(len(l)-1, -1, -1), reversed(l))

Have a look at my answer here for more context.

秋心╮凉 2024-08-14 13:25:54
def reverseGenerator(gen):
     new = [i for i in gen]
     yield new[::-1][0]
     new.pop()
     yield from reverseGenerator(i for i in new)
def reverseGenerator(gen):
     new = [i for i in gen]
     yield new[::-1][0]
     new.pop()
     yield from reverseGenerator(i for i in new)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文