Родная сопрограмма и стоп-изменение - PullRequest
0 голосов
/ 04 мая 2018

Рассмотрим эту простую сопрограмму

In [9]: async def coro():                  
   ...:     print('hello world')           
   ...:

Мы знаем, что эти сопрограммы не являются итераторами

In [12]: type(c)     
Out[12]: coroutine   

In [13]: next(c)     
---------------------------------------------------------------------------           
TypeError                      Traceback (most recent call last)           
<ipython-input-13-e846efec376d> in <module>()                                         
----> 1 next(c)      

TypeError: 'coroutine' object is not an iterator 

Однако, если я запускаю сопрограмму, я получаю ошибку StopIteration.

In [10]: c = coro()  

In [11]: c.send(None)
hello world          
---------------------------
StopIteration                      Traceback (most recent call last)           
<ipython-input-11-d9162d5dda48> in <module>()                                         
----> 1 c.send(None) 

StopIteration:

это отвечает, что нативные сопрограммы функционально эквивалентны сгенерированным основанным сопрограммам. Но другой ответ на тот же вопрос идет дальше и объясняет, как они служат отдельным целям.

Является ли единственная причина, по которой собственные coros вызывают ошибку StopIteration, заключается в том, что они делятся значительным кодом с coros на основе генератора? или есть и другая причина?

1 Ответ

0 голосов
/ 04 мая 2018

Я не думаю, что кто-то конкретно обсуждал это как явный выбор дизайна при обсуждении PEP 492 , но я думаю, что это не просто , когда они делятся значительным кодом, но также и то, что они должны быть настолько взаимозаменяемыми, насколько это возможно. Если какая-то другая реализация Python по какой-то причине строит async coros и yield from coros по-разному, они все равно должны быть такими же взаимозаменяемыми, как и в CPython (так что, например, вы можете запустить asyncio код, написанный для Python 3.4).

Во всяком случае, даже если обоснование нигде не закреплено в столь многих словах, решение явно задокументировано в PEP под Методы объекта сопрограммы :

Сопрограммы основаны на генераторах внутри, поэтому они разделяют реализацию. Подобно объектам-генераторам, сопрограммы имеют методы throw(), send() и close(). StopIteration и GeneratorExit играют одинаковую роль для сопрограмм ...

И еще одна вещь, которую сделал , как часть обсуждения async for, заключается в том, что асинхронный итератор не может вызвать StopIteration. И если бы дизайн каким-то образом изменился, чтобы асинхронные итераторы могли его поднять, это сделало бы невозможным создание асинхронных итераторов с обычными генераторами. Итак, новое исключение StopAsyncIteration было создано. В этот момент стало ясно, что на самом деле не существует случая, когда coro или нормальный генератор явно повышают StopIteration, следовательно, PEP 479 (который был применен к асинхронному coros немедленно, но был обнаружен в течение нескольких версии для традиционных генераторов). См. Почему StopAsyncIteration.

...