diff --git a/docs/source/kinds_of_types.rst b/docs/source/kinds_of_types.rst index b1b6648b0c1cc..7cdedf6718670 100644 --- a/docs/source/kinds_of_types.rst +++ b/docs/source/kinds_of_types.rst @@ -721,7 +721,7 @@ For more details, see :ref:`type-variable-value-restriction`. Generators ********** -A basic generator that only yields values can be annotated as having a return +A basic generator that only yields values can be succinctly annotated as having a return type of either :py:class:`Iterator[YieldType] ` or :py:class:`Iterable[YieldType] `. For example: .. code-block:: python @@ -729,10 +729,21 @@ type of either :py:class:`Iterator[YieldType] ` or :py:class:`I def squares(n: int) -> Iterator[int]: for i in range(n): yield i * i + +A good rule of thumb is to annotate functions with the most specific return +type possible. However, you should also take care to avoid leaking implementation +details into a function's public API. In keeping with these two principles, prefer +:py:class:`Iterator[YieldType] ` over +:py:class:`Iterable[YieldType] ` as the return-type annotation for a +generator function, as it lets mypy know that users are able to call :py:func:`next` on +the object returned by the function. Nonetheless, bear in mind that ``Iterable`` may +sometimes be the better option, if you consider it an implementation detail that +``next()`` can be called on the object returned by your function. If you want your generator to accept values via the :py:meth:`~generator.send` method or return -a value, you should use the -:py:class:`Generator[YieldType, SendType, ReturnType] ` generic type instead. For example: +a value, on the other hand, you should use the +:py:class:`Generator[YieldType, SendType, ReturnType] ` generic type instead of +either ``Iterator`` or ``Iterable``. For example: .. code-block:: python @@ -755,7 +766,7 @@ annotated the first example as the following: for i in range(n): yield i * i -This is slightly different from using ``Iterable[int]`` or ``Iterator[int]``, +This is slightly different from using ``Iterator[int]`` or ``Iterable[int]``, since generators have :py:meth:`~generator.close`, :py:meth:`~generator.send`, and :py:meth:`~generator.throw` methods that -generic iterables don't. If you will call these methods on the returned -generator, use the :py:class:`~typing.Generator` type instead of :py:class:`~typing.Iterable` or :py:class:`~typing.Iterator`. +generic iterators and iterables don't. If you plan to call these methods on the returned +generator, use the :py:class:`~typing.Generator` type instead of :py:class:`~typing.Iterator` or :py:class:`~typing.Iterable`.