@PesyCorm

Почему в приведенном примере есть разница в расположении raise StopAsyncIteration?

Привет!
Попытался реализовать простой асинк генератор, но споткнулся в самом начале об непонимание работы async for.
Мой пример выглядит так (это работающий вариант):
class ARange:

    def __init__(self, number):
        self.r = self.range(number)

    async def range(self, number):
        for el in range(number):
            yield el

    async def __anext__(self):
        async for x in self.r:
            return x
        else:
            raise StopAsyncIteration

    def __aiter__(self):
        return self


async def amain():
    aiter = ARange(10)
    async for i in aiter:
        print(i)


asyncio.run(amain())

Однако, если я перемещу исключение из __anext__ в основной цикл, то он не будет отрабатывать
__anext__
async def __anext__(self):
        async for x in self.r:
            return x

main
async def amain():
    aiter = ARange(10)
    async for i in aiter:
        print(i)
    else:
        raise StopAsyncIteration

В данном случае программа будет выполняться бесконечно и после вывода всех чисел из range будет выводить None.
Почему так происходит и в чем заключается разница в расположении raise в данном примере?
  • Вопрос задан
  • 44 просмотра
Решения вопроса 1
Vindicar
@Vindicar
RTFM!
Я подозреваю, что по исчерпанию self.r (а range() - это не список, это одноразовая последовательность!) попытка вхождения в async for x in self.r приведёт к тому, что self.r просигнализирует об исчерпании последовательности. Как следствие, тело async for не выполнится ни разу, и управление выйдет за цикл. А за циклом - ничего, конец корутины. Поэтому, так как явного return не было, будет неявный return None. Что ты и наблюдаешь.
Соответственно, ты никогда не получишь выброс StopIteration - его будет выкидывать self.r.__anext__(), но исключение будет перехватываться async for.
Так что нужно добавить raise StopIteration() после async for, чтобы по опустошению self.r оно гарантировано выбрасывалось.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы