- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
灵感来自 my own answer ,我什至不明白它是如何工作的,请考虑以下内容:
def has22(nums):
it = iter(nums)
return any(x == 2 == next(it) for x in it)
>>> has22([2, 1, 2])
False
我希望引发 StopIteration
,因为在到达 2
时,next(it)
将推进一个消耗的迭代器。然而,这种行为似乎已被完全禁用,仅适用于生成器表达式!一旦发生这种情况,生成器表达式似乎会立即中断
。
>>> it = iter([2, 1, 2]); any(x == 2 == next(it) for x in it)
False
>>> it = iter([2, 1, 2]); any([x == 2 == next(it) for x in it])
Traceback (most recent call last):
File "<pyshell#114>", line 1, in <module>
it = iter([2, 1, 2]); any([x == 2 == next(it) for x in it])
StopIteration
>>> def F(nums):
it = iter(nums)
for x in it:
if x == 2 == next(it): return True
>>> F([2, 1, 2])
Traceback (most recent call last):
File "<pyshell#117>", line 1, in <module>
F([2, 1, 2])
File "<pyshell#116>", line 4, in F
if x == 2 == next(it): return True
StopIteration
即使这样也行!
>>> it=iter([2, 1, 2]); list((next(it), next(it), next(it), next(it))for x in it)
[]
所以我想我的问题是,为什么要为生成器表达式启用此行为?
注意: 3.x
最佳答案
开发人员认为允许这是一个错误,因为它可以掩盖隐藏的错误。因此,接受 PEP 479 意味着这将消失。
在 Python 3.5 中,如果您执行 from __future__ import generator_stop
,而在 Python 3.7 中,默认情况下,问题中的示例将失败并返回 RuntimeError
。您仍然可以使用一些 itertools 魔法实现相同的效果(允许不预先计算 nums
):
from itertools import tee, islice
def has22(nums):
its = tee(nums, 2)
return any(x == y == 2 for x, y in
zip(its[0], islice(its[1], 1, None)))
它首先起作用的原因与生成器的工作方式有关。你可以想到这个 for 循环:
for a in b:
# do stuff
(大致)等同于此:
b = iter(b)
while True:
try:
a = next(b)
except StopIteration:
break
else:
# do stuff
现在,所有示例都有 两个 for 循环嵌套在一起(一个在生成器表达式中,一个在使用它的函数中),因此当外部循环执行其 next
时,内部循环迭代一次称呼。当内部循环中的“#do stuff”为 raise StopIteration
时会发生什么?
>>> def foo(): raise StopIteration
>>> list(foo() for x in range(10))
[]
异常传播到内部循环之外,因为它不在内部循环中,并被外部 循环捕获。在新行为下,Python 将拦截即将从生成器传播出去的 StopIteration
并将其替换为 RuntimeError
,不会被包含的 for 循环捕获。
这也意味着这样的代码:
def a_generator():
yield 5
raise StopIteration
也会失败,并且邮件列表线程给人的印象是这无论如何都被认为是错误的形式。正确的做法是:
def a_generator():
yield 5
return
正如您所指出的,列表理解的行为已经有所不同:
>>> [foo() for x in range(10)]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <listcomp>
File "<stdin>", line 1, in foo
StopIteration
这在某种程度上是一个实现细节泄漏 - 列表推导不会被转换为对具有等效生成器表达式的 list
的调用,显然这样做 would cause large performance penalties 的权力被认为是禁止的。
关于python - 生成器表达式从不引发 StopIteration,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16814111/
我正在编写从 azure DevOps 下载大型审计日志 csv 文件并根据给定条件过滤数据的脚本。这适用于小 csv 文件,但对于具有大数据的文件,它会失败 字段 = 下一个(读者) 停止迭代 有人
这是我的代码 class A: pass def f(): yield A() def g(): it = f() next(it).a = next(it, None
以下是 Jean 对我的问题的回答:Python converting strings in a list to numbers ,运行下面的最小代码时出现 StopIteration 异常。 pri
我正在 Python 中实现一个迭代器,它包装另一个迭代器,并在传递迭代器的输出之前对其输出进行后处理。下面是一个简单的示例,它采用一个返回字符串的迭代器,并在每个字符串前面添加 FILTERED B
看看这个,问题的症结在最下面: >>> scan = iter('FHUR203459') >>> while True: print(next(scan)) F H U R 2 0
我想编写一个生成器,它可以接受来自产量的有限数量的输入,然后优雅地处理更多输入。捕获 StopIteration 的最佳方法是什么? 我尝试使用内部生成器与外部生成器进行包装,使用 try- exce
为什么这段代码抛出“StopIteration”: stub_generator = (x for x in range(5)) stub_dict = {} stub_dict[next(stub_
我有一个生成器,我想确认它已经结束(在程序的某个点。我在 python 2.7 中使用 unittest # it is a generator whould have only one item i
为什么多次调用耗尽的生成器时,StopIteration 每次都会引发,而不是仅在第一次尝试时引发?后续调用不是没有意义,并表明调用方代码中可能存在错误吗? def gen_func(): y
当迭代器耗尽时,最后一次从迭代器返回某些东西的好方法是什么。我正在使用一个标志,但这相当丑陋: class Example(): def __iter__(self): sel
我想从一个 csv 文件中读取最多 20 行: rows = [csvreader.next() for i in range(20)] 如果文件有 20 行或更多行则工作正常,否则会失败并出现 St
灵感来自 my own answer ,我什至不明白它是如何工作的,请考虑以下内容: def has22(nums): it = iter(nums) return any(x ==
我有一个 generator检查列表中某个条件的对象。这个程序适用于我的所有情况。 但我只想澄清一些关键点。 在我的程序中每当generator yield值 'No'或 'Done'控制迭代停止并调
我需要捕获 next(it) 抛出的异常,因此在这种情况下我无法使用常规的 for 循环。所以我写了这段代码: it = iter(xrange(5)) while True: try:
我的作业代码遇到了一些问题,我应该浏览一个文本文件并找到四月份的生日并打印它们。文本文件如下所示: 鲍勃,6 月 10 日 乔,4 月 12 日 苏,7 月 22 日 我应该检查一下并打印出四月份的姓
我正在使用 yield from,但我不知道 while 对 yield 的影响。如果我将 yield from 放入 while 循环中,效果很好,但是当我同时取消循环时,会发生异常。 final_
我想遍历两个不同大小的列表,但速度不同(我只找到了并行迭代的答案)。例如,考虑两个包含相同类型元素的排序列表,我想根据它们只在一个列表或两个列表中的事实对元素执行某些操作,使用两个列表的公共(publ
我正在编写一个从文件接收输入的程序,每一行都可能包含“ATG”或“GTG”,我很确定我所做的一切都是我想做的。这是我第一次在 python 中使用生成器,在研究了这个问题之后,我仍然不知道为什么我会停
我有一个函数可以使用生成器计算毕达哥拉斯三元组。但是,当我调用 next(myfunc()) 时,它会抛出此错误: Traceback (most recent call last): File
如果我有多个可迭代对象作为参数,有没有办法让代码在列表之一引发 StopIteration 之后继续运行? 我不能使用任何切片、len() 或任何 itertools。 这是我迄今为止尝试过的方法,我
我是一名优秀的程序员,十分优秀!