Как решить проблему со StopIteration через except?
Дан код, он объединяет числа из двух списков в кортеж по индексам
def generate_something_2(l1, l2):
try:
min_i = len(l1) if len(l1) < len(l2) else len(l2)
for i in range(0, min_i):
yield l1[i], l2[i]
except StopIteration:
pass
l3 = generate_something_2([3, 2, 1, 1], [4, 3, 2])
print(next(l3))
print(next(l3))
print(next(l3))
На выходе получается
(3, 4)
(2, 3)
(1, 2)
но если добавить ещё один print(next(l3)) то вылезает ошибка
...
print(next(l3))
StopIteration
хотя я сделал except, но он не работает. Что бы я не писал в except StopIteration:, код всё равно продолжает выдавать ошибку. Как это исправить?
Ответы (1 шт):
Вы не совсем правильно понимаете логику StopIteration
Он не возникает внутри функции-генератора, поэтому внутри неё перехватить это исключение невозможно. Это исключение возникает тогда, когда когда внутри функции-генератора весь код уже отработал, а внешний код требует очередной элемент.
Если вы хотите, чтобы из функции-генератора можно было неограниченное количество раз требовать следующий элемент, то вы должны переписать её так, чтобы она всегда могла вернуть ещё один элемент, и никогда бы не дошла до конца своего кода:
def generate_something_2(l1, l2):
min_i = len(l1) if len(l1) < len(l2) else len(l2)
for i in range(0, min_i):
yield l1[i], l2[i]
# Вот так вот
while True:
yield None
l3 = generate_something_2([3, 2, 1, 1], [4, 3, 2])
print(next(l3))
print(next(l3))
print(next(l3))
print(next(l3))
print(next(l3))
print(next(l3))
# Вывод:
# (3, 4)
# (2, 3)
# (1, 2)
# None
# None
# None
Либо, если вы всё-таки хотите перехватывать StopIteration, то нужно делать это не внутри функции-генератора, а в том коде, который её использует:
def generate_something_2(l1, l2):
min_i = len(l1) if len(l1) < len(l2) else len(l2)
for i in range(0, min_i):
yield l1[i], l2[i]
l3 = generate_something_2([3, 2, 1, 1], [4, 3, 2])
while True:
try:
print(next(l3))
except StopIteration:
print('Генератор исчерпан')
break
# Вывод:
# (3, 4)
# (2, 3)
# (1, 2)
# Генератор исчерпан