在检查了几个简单的测试后,似乎从循环中断到结束生成器而不是引发StopIteration异常似乎更快。如果停止生成器的标准和可接受的方法正在使用异常,为什么会出现这种情况。 source
In [1]: def f():
....: for i in range(1024):
....: yield None
....: break
....:
In [2]: def g():
....: for i in range(1024):
....: yield None
....: raise StopIteration
....:
In [3]: %timeit for i in f(): pass
1000000 loops, best of 3: 1.22 µs per loop
In [4]: %timeit for i in g(): pass
100000 loops, best of 3: 5.9 µs per loop
In [5]: %timeit for i in f(): pass
1000000 loops, best of 3: 1.22 µs per loop
In [6]: %timeit for i in g(): pass
100000 loops, best of 3: 5.82 µs per loop
答案 0 :(得分:28)
如果停止生成器的标准和可接受的方法正在使用异常,为什么会这样呢。
仅当生成器不再生成任何内容时才会引发异常StopIteration
。并且,它不是中途停止发电机的标准方式。
以下是有关如何正确阻止它们的生成器文档中的两个声明:
......该提案还清除了关于如何终止a的混淆 生成器:正确的方法是
return
,而不是raise StopIteration
。
Q值。为什么要允许
"return"
?为什么不强制终止拼写"raise StopIteration"
?一个。
StopIteration
的机制是低级细节,非常类似于 Python 2.1中的IndexError机制:实现需要 在隐藏的内容中定义某些,并公开Python 这些机制适合高级用户。这不是一个论据 然而,迫使每个人都在这个层面上工作。"return"
表示"我是 完成"在任何类型的功能,这很容易解释和使用。 请注意,"return"
并不总是等同于"raise StopIteration"
在try / except构造中,(参见"规范:返回" 部分)。
因此,正确的方法是使用return
语句,而不是使用break
或raise StopIteration
。
似乎从循环中
break
更快结束生成器而不是引发StopIteration
异常。
确实是因为在提出异常时还有更多的工作要做。您可以使用dis
模块查看字节码:
In [37]: dis.dis(f)
2 0 SETUP_LOOP 26 (to 29)
3 LOAD_GLOBAL 0 (range)
6 LOAD_CONST 1 (1024)
9 CALL_FUNCTION 1
12 GET_ITER
>> 13 FOR_ITER 12 (to 28)
16 STORE_FAST 0 (i)
3 19 LOAD_CONST 0 (None)
22 YIELD_VALUE
23 POP_TOP
4 24 BREAK_LOOP
25 JUMP_ABSOLUTE 13
>> 28 POP_BLOCK
>> 29 LOAD_CONST 0 (None)
32 RETURN_VALUE
In [38]: dis.dis(g)
2 0 SETUP_LOOP 31 (to 34)
3 LOAD_GLOBAL 0 (range)
6 LOAD_CONST 1 (1024)
9 CALL_FUNCTION 1
12 GET_ITER
>> 13 FOR_ITER 17 (to 33)
16 STORE_FAST 0 (i)
3 19 LOAD_CONST 0 (None)
22 YIELD_VALUE
23 POP_TOP
4 24 LOAD_GLOBAL 2 (StopIteration)
27 RAISE_VARARGS 1
30 JUMP_ABSOLUTE 13
>> 33 POP_BLOCK
>> 34 LOAD_CONST 0 (None)
37 RETURN_VALUE
您可以看到几乎所有内容都相同但是为了引发异常,它必须执行一些额外的指令:
24 LOAD_GLOBAL 2 (StopIteration)
27 RAISE_VARARGS 1
答案 1 :(得分:4)
如果你做了休息,那么它只是退出循环,在你的情况下没有更多的事情要做,所以它也退出了这个功能。 如果你引发异常,那么它仍然必须处理后台发生的所有异常事件。
more work == more execution time
可以使用StopIteration的原因(我从来没有使用过那个,所以不要引用我)是为了以后捕获它,或者只是退出嵌套循环。 我只是快速查看了您提供的源代码,在我看来,StopIteration仅用于说明生成器如何工作,但它不用于生成器。
我希望能回答你的问题。