Ответ 1
Почему это так, если стандартный и принятый метод остановки генератора использует исключение.
Исключение StopIteration
возникает только тогда, когда генератору больше ничего не нужно. И это не стандартный способ остановки генератора на полпути.
Вот два утверждения из документации генераторов о том, как их правильно остановить:
... предложение также устраняет путаницу в том, как прекратить генератор: правильный путь
return
, а неraise StopIteration
.
Q. Зачем разрешать
"return"
вообще? Почему не требуется принудительное завершение"raise StopIteration"
?а. Механика
StopIteration
представляет собой детали низкого уровня, похожие на механика IndexError в Python 2.1: реализация должна сделать что-то хорошо определенное под обложками, а Python предоставляет эти механизмы для продвинутых пользователей. Это не аргумент для заставляя всех работать на этом уровне."return"
означает "Я сделано" в любой функции, и это легко объяснить и использовать. Обратите внимание, что"return"
не всегда эквивалентно"raise StopIteration"
в try/except construct (см. "Спецификация: Возврат" ) раздел).
Таким образом, правильным способом было бы использовать оператор 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