我已经制作了一个生成器来逐字读取文件,它可以很好地工作。
def word_reader(file):
for line in open(file):
for p in line.split():
yield p
reader = word_reader('txtfile')
next(reader)
在列表中获取n个下一个值的最简单方法是什么?
答案 0 :(得分:47)
使用itertools.islice
:
list(itertools.islice(it, n))
答案 1 :(得分:11)
编辑:使用itertools.islice
。我最初提出的模式是个坏主意 - 当it
产生的值小于n
时崩溃,这种行为取决于细微的问题,所以阅读这些代码的人不太可能理解它的精确语义。
还有
[next(it) for _ in range(n)]
对于不熟悉itertools的人来说可能更清楚;但是如果你经常处理迭代器,那么itertools对你的工具集来说是一个有价值的补充。
next(it)
用尽并且提升StopIteration
会怎样?(即当it
的值小于n
时)
几年前,当我写上面这一行时,我可能认为StopIteration
会产生干净地终止列表理解的聪明副作用。但不,整个理解都会通过StopIteration
向上崩溃。 (只有当异常来自range(n)
迭代器时才会干净地退出。)
这可能不是你想要的行为。
但它变得更糟。以下应该等同于列表理解(特别是在Python 3上):
list(next(it) for _ in range(n))
不是。内部部分是发电机功能的简写; list()
知道在任何地方StopIteration
提升时就已经完成了
=>当没有n
值并返回较短列表时,此版本可以安全地处理。 (比如itertools.islice()
。)
但这也会改变!当一个生成器StopIteration
中的任何代码引发RuntimeError
时,生成器默默地退出的事实是一个已知的疣,由PEP 479解决。从Python 3.7(或将来导入的3.5)将导致{{1}}而不是干净地完成生成器。即它会变得类似于列表理解的行为。
(在最近的HEAD版本中测试过)
答案 2 :(得分:3)
for word, i in zip(word_reader(file), xrange(n)):
...
答案 3 :(得分:2)
要获取生成器的前n个值,可以使用more_itertools.take。
如果您计划迭代块中的单词(例如,一次100个),您可以使用more_itertools.chunked(https://more-itertools.readthedocs.io/en/latest/api.html):
import more_itertools
for words in more_itertools.chunked(reader, n=100):
# process 100 words
答案 4 :(得分:0)
使用cytoolz.take。
>>> from cytoolz import take
>>> list(take(2, [10, 20, 30, 40, 50]))
[10, 20]