如何在列表中获取生成器的n个下一个值(python)

Pet*_*mit 41 python list generator

我已经制作了一个生成器来逐字读取文件,它运行良好.

def word_reader(file):
    for line in open(file):
        for p in line.split():
            yield p

reader = word_reader('txtfile')
next(reader)
Run Code Online (Sandbox Code Playgroud)

在列表中获取n个下一个值的最简单方法是什么?

Ign*_*ams 57

用途itertools.islice:

list(itertools.islice(it, n))
Run Code Online (Sandbox Code Playgroud)

  • 考虑`islice()`的参数的一种简单方法是它们完全镜像`range()`的参数:`islice([start,] stop [,step])`(限制为步骤> 0 ) (7认同)
  • @BeniCherniavsky-Paskin:虽然有一个怪癖,但 `stop` 可以明确为 `None`,这意味着 `islice` 对象本身永远不会停止迭代,除非底层的可迭代对象停止。在那个用例中,你试图跳过元素(`start` 的初始元素,`step > 1` 的产量之间的 `step-1` 元素),而不是在你获得足够远的距离后截断输入。`range` 不接受 `None` 作为 `stop` 值(`itertools.count` 填补了那个利基),所以使用 `range` 的抽象只是一个漏洞。 (3认同)
  • @Dave是的,的确如此.0也可以省略,因为它是可选的. (2认同)

Ben*_*kin 13

编辑:使用itertools.islice.我最初提出的模式是个坏主意 - 当it收益率低于n值时崩溃,这种行为取决于微妙的问题,所以阅读这些代码的人不太可能理解它的精确语义.

还有

[next(it) for _ in range(n)]
Run Code Online (Sandbox Code Playgroud)

哪个(?)对于不熟悉itertools的人来说更清楚; 但是如果你经常处理迭代器,那么itertools对你的工具集来说是一个有价值的补充.

如果next(it)筋疲力尽又会引发StopIteration什么?

(即,当收益率it低于n收益率时)

几年前我写这篇文章的时候,我可能认为一个StopIteration聪明的副作用就是干净地终止列表理解.但不,整个理解都会在StopIteration向上传递时崩溃.(只有当异常来自range(n)迭代器时才会干净地退出.)

这可能不是你想要的行为.

但它变得更糟.以下应该等同于列表理解(特别是在Python 3上):

list(next(it) for _ in range(n))
Run Code Online (Sandbox Code Playgroud)

事实并非如此.内部部分是发电机功能的简写; list()知道它在StopIteration 任何地方升起时都会完成.
=>当没有n值时,此版本可以安全地处理并返回较短的列表.(喜欢itertools.islice().)

[上处决:2.7,3.4 ]

但这也会改变!当它内部的任何代码引发时,发生器默默地退出的事实StopIteration是已知的疣,由PEP 479解决.从Python 3.7(或将来导入的3.5)将导致RuntimeError而不是干净地完成生成器.即它将变得类似于列表理解的行为.(在最近的HEAD版本上测试过)

  • 如果您不介意虚假值,您可以使用“next”函数的默认参数并调用,例如“[next(it, None) for _ in range(n)]” (2认同)