Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在列表中获取生成器的n个下一个值(python)_Python_List_Generator - Fatal编程技术网

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

如何在列表中获取生成器的n个下一个值(python),python,list,generator,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) 获取列表中n个下一个值的最简单方法是什么?使用itertools.islice: list(itertools.islice(it, n)) 编辑:使

我已经做了一个生成器来逐字读取文件,它工作得很好

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

reader = word_reader('txtfile')
next(reader)

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

使用
itertools.islice

list(itertools.islice(it, n))

编辑:使用
itertools.islice
。我最初提出的下面的模式是一个坏主意——当
it
产生的值小于
n
时,它就会崩溃,而这种行为取决于微妙的问题,因此阅读此类代码的人不太可能理解它的精确语义

还有

[next(it) for _ in range(n)]
对于不熟悉itertools的人来说,这可能更清楚;但是,如果您经常使用迭代器,那么itertools是一个值得添加到工具集的工具

如果
next(it)
耗尽并引发
StopIteration
,会发生什么情况? (即当
时,其
产生的值小于
n
时)

当我几年前写这一行时,我可能认为
StopIteration
会有一个聪明的副作用,即干净地终止列表理解。但是不,通过向上传递
StopIteration
,整个理解将崩溃。(只有当异常源于
范围(n)
迭代器时,它才会干净地退出。)

这可能不是你想要的行为

但情况变得更糟了。以下内容应该与列表理解相当(尤其是在Python 3上):

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

[执行日期:,]

但这太难改变了!当生成器中的任何代码引发
StopIteration
时,生成器会自动退出,这是一个已知的缺点,由解决。从Python3.7(或未来导入的3.5)开始,这将导致
运行时错误
,而不是干净地完成生成器。也就是说,它将变得类似于列表的行为。
(在最近的头部构建上测试)

要获取生成器的前n个值,可以使用

如果您计划以块的形式迭代单词(例如,一次迭代100个),您可以使用更多的\u itertools.chunked():

使用


步长值默认为1,因此可以省略:
list(itertools.islice(it,0,n))
@Dave确实如此。也可以省略0,因为它是可选的。思考
islice()
的参数的一个简单方法是,它们完全反映
range()
的参数:
islice([start,]stop[,step])
(有步骤>0的限制)@BeniCherniavsky Paskin:尽管有一个怪癖,在这种情况下,
stop
可以显式地设置为
None
,这意味着
islice
对象本身永远不会停止迭代,除非底层iterable停止。在这种情况下,您试图跳过元素(开始时的初始元素,
step-1时的
step-1时的
elements之间的元素,
step>1时的
),而不是在足够远的地方截断输入
range
不接受
None
作为
stop
值(
itertools.count
填补了这个空缺),因此使用
range
的抽象只是一个标题漏洞。是的,也不错。我认为islice解决方案更好一些,所以我会接受它。当然这个答案更好,因为它更简单,不需要额外的模块导入,括号更少。。。也许在Python4中,切片默认返回生成器(与Py3中的映射相比)。我只想将
I
更改为
\u
,以便在某些IDE中没有“未使用的变量”警告;)。顺便说一句,在Haskell中,它被称为
take N
,这是一个完美的函数。除非N大于生成器的长度,否则您将得到一个StopIteration和一个未定义的变量。@xApple oops,您是对的!如果将其写成列表(genartor expr.),则会有令人困惑的不同。为了解释这一点,编辑了向上投票的
islice
。如果您不介意伪值,您可以使用
next
函数的默认参数并调用,例如
[next(it,None)for uu in range(n)]
这是错误的,因为它会消耗生成器中的额外元素。Beni的答案不是这样的。如果您对i、word-in-zip(xrange(n)、word\u阅读器(文件)):
执行
,则可以避免这种一次性操作。虽然我更喜欢一个可靠的bug,而不是如此脆弱的依赖顺序的“修复”:-,但这似乎是只使用原语的最简单的方法;我没有标记,因为我需要仔细查看并决定关闭哪一个。我在更多的itertools中查看了
take
的源代码,在我看来
take
的定义只是
list(islice(iterable,n))
。因此,如果您不想为此安装单独的软件包,那么使用
islice
解决方案应该没有任何缺点。
list(next(it) for _ in range(n))
for word, i in zip(word_reader(file), xrange(n)):
    ...
import more_itertools
for words in more_itertools.chunked(reader, n=100):
    # process 100 words
>>> from cytoolz import take
>>> list(take(2, [10, 20, 30, 40, 50]))
[10, 20]