Несмотря на то, что генераторы в основном используют ключевое слово yield для возврата очередного значения, return из них никуда не делся. При использовании функции как генератора return позволяет досрочно его завершить.
Слегка модифицируем наш генератор: теперь он завершается автоматически, если очередное число оказалось больше 100000:
from collections.abc import Iterator
def pow_two(max_pow: int) -> Iterator:
cur_pow = 0
while cur_pow <= max_pow:
yield 2 ** cur_pow
cur_pow += 1
# Если следующее число больше 10000,
# прерываем итератор
if 2 ** cur_pow > 100000:
return
# Попробуем вывести степени двойки от 2^0 до 2^100
for i in pow_two(100):
print(i)
При этом на самом деле выведутся только числа от 1 до 65536, потому что 131072 (следующая степень двойки) больше 100000:
1
2
4
8
16
32
64
128
256
512
1024
2048
4096
8192
16384
32768
65536
Если переписать цикл for, то можно заметить, что на самом деле ключевое слово return в генераторах выбрасывает уже знакомое нам исключение StopIteration:
from collections.abc import Iterator
def pow_two(max_pow: int) -> Iterator:
cur_pow = 0
while cur_pow <= max_pow:
yield 2 ** cur_pow
cur_pow += 1
if 2 ** cur_pow > 100000:
return 'Next number is greater than 100000'
pt = pow_two(100)
while True:
print(next(pt))
На экран выведется следующее:
1
2
4
8
16
32
64
128
256
512
1024
2048
4096
8192
16384
32768
65536
Traceback (most recent call last):
File "main.py", line 15, in <module>
print(next(pt))
StopIteration: Next number is greater than 100000
Process finished with exit code 1
Если указать после return какое-то значение, оно выведется вместе с исключением в качестве пояснения.
<aside>
👉 Можно заметить, что и без явного return генератор рано или поздно вернёт StopIteration. Это происходит потому, что в конце функции всегда происходит неявный return без каких-либо значений.
</aside>