-
-
Notifications
You must be signed in to change notification settings - Fork 35.3k
gh-141984: Move generator iterator reference out of syntax docs #154884
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
415b5e0
bf9219f
15b982e
9e5ce42
80e390b
02b643f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -891,10 +891,12 @@ many numeric contexts, ``False`` and ``True`` behave like the integers 0 and 1, | |||||
| However, relying on this is discouraged; explicitly convert using :func:`int` | ||||||
| instead. | ||||||
|
|
||||||
| .. _iterator-types: | ||||||
|
|
||||||
| .. _typeiter: | ||||||
|
|
||||||
| Iterator Types | ||||||
| ============== | ||||||
| Iteration-related Types | ||||||
| ======================= | ||||||
|
|
||||||
| .. index:: | ||||||
| single: iterator protocol | ||||||
|
|
@@ -907,6 +909,9 @@ using two distinct methods; these are used to allow user-defined classes to | |||||
| support iteration. Sequences, described below in more detail, always support | ||||||
| the iteration methods. | ||||||
|
|
||||||
| Iterables | ||||||
| --------- | ||||||
|
|
||||||
| One method needs to be defined for container objects to provide :term:`iterable` | ||||||
| support: | ||||||
|
|
||||||
|
|
@@ -923,10 +928,14 @@ support: | |||||
| :c:member:`~PyTypeObject.tp_iter` slot of the type structure for Python | ||||||
| objects in the Python/C API. | ||||||
|
|
||||||
| .. _stdtypes-iterators: | ||||||
|
|
||||||
| Iterators | ||||||
| --------- | ||||||
|
|
||||||
| The iterator objects themselves are required to support the following two | ||||||
| methods, which together form the :dfn:`iterator protocol`: | ||||||
|
|
||||||
|
|
||||||
| .. method:: iterator.__iter__() | ||||||
|
|
||||||
| Return the :term:`iterator` object itself. This is required to allow both | ||||||
|
|
@@ -958,13 +967,275 @@ Implementations that do not obey this property are deemed broken. | |||||
| Generator Types | ||||||
| --------------- | ||||||
|
|
||||||
| Python's :term:`generator`\s provide a convenient way to implement the iterator | ||||||
| protocol. If a container object's :meth:`~object.__iter__` method is implemented as a | ||||||
| generator, it will automatically return an iterator object (technically, a | ||||||
| generator object) supplying the :meth:`~iterator.__iter__` and :meth:`~generator.__next__` | ||||||
| methods. | ||||||
| More information about generators can be found in :ref:`the documentation for | ||||||
| the yield expression <yieldexpr>`. | ||||||
| Python's :term:`generators <generator>` -- or more precisely, | ||||||
| :term:`generator functions <generator function>` and | ||||||
| :term:`generator iterators <generator iterator>` -- provide a convenient way | ||||||
| to implement the iterator protocol. | ||||||
|
|
||||||
| A function that contains one or more :ref:`yield expressions <yieldexpr>` | ||||||
| is a :term:`generator function`. | ||||||
| For example:: | ||||||
|
|
||||||
| >>> def count_to_three(): | ||||||
| ... yield 0 | ||||||
| ... yield 1 | ||||||
| ... yield 2 | ||||||
| ... yield 3 | ||||||
|
|
||||||
| Generator functions behave as regular | ||||||
| :ref:`user-defined functions <user-defined-funcs>` | ||||||
| (for example, they have the same attributes), except that calling a generator | ||||||
| function returns a :ref:`generator iterator <generator-methods>`:: | ||||||
|
|
||||||
| >>> count_to_three() | ||||||
| <generator object count_to_three at 0x7f33a2305000> | ||||||
|
|
||||||
| Iterating a generator iterator executes code of the underlying | ||||||
| generator function, producing each :keyword:`yield`\ed value in turn:: | ||||||
|
|
||||||
| >>> for number in count_to_three(): | ||||||
| ... print(number) | ||||||
| 0 | ||||||
| 1 | ||||||
| 2 | ||||||
| 3 | ||||||
|
|
||||||
| >>> list(count_to_three()) | ||||||
| [0, 1, 2, 3] | ||||||
|
|
||||||
| One common use for generator functions is implementing the | ||||||
| :meth:`~object.__iter__` method of custom iterable objects. | ||||||
| For example:: | ||||||
|
|
||||||
| >>> class CardDeck: | ||||||
| ... def __iter__(self): | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Inconsistent indentation. |
||||||
| ... yield 'three of clubs' | ||||||
| ... yield 'ace of hearts' | ||||||
|
|
||||||
| >>> list(CardDeck()) | ||||||
| ... ['three of clubs', 'ace of hearts'] | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
|
|
||||||
| .. index:: pair: object; generator | ||||||
| .. _generator-methods: | ||||||
|
|
||||||
| Generator iterators | ||||||
| ^^^^^^^^^^^^^^^^^^^ | ||||||
|
|
||||||
| Generator iterators implement the | ||||||
| :ref:`iterator protocol <stdtypes-iterators>`. | ||||||
| Iterating them drives execution of the underlying generator function. | ||||||
|
|
||||||
| .. index:: pair: exception; StopIteration | ||||||
|
|
||||||
| .. method:: generator.__next__() | ||||||
|
|
||||||
| Starts the execution of a generator function or resumes it at the | ||||||
| :ref:`yield expression <yieldexpr>` where the function is currently suspended. | ||||||
| When a generator function is resumed with a :meth:`~generator.__next__` | ||||||
| method, the current yield expression always evaluates to :const:`None`. | ||||||
| The execution then continues to the next yield expression, where the | ||||||
| generator is suspended again, and the value of the expression after the | ||||||
| :keyword:`yield` keyword is returned to :meth:`~generator.__next__`'s | ||||||
| caller. | ||||||
| If the generator exits without yielding another value, | ||||||
| :meth:`~generator.__next__` raises a :exc:`StopIteration` exception, | ||||||
| signalling that iteration has completed. | ||||||
|
|
||||||
| This method is normally called implicitly, for example by a :keyword:`for` | ||||||
| loop, or by the built-in :func:`next` function. | ||||||
|
|
||||||
| Generator iterators have a few more methods than generic iterators, which | ||||||
| can be used to control the execution of the underlying generator function: | ||||||
|
|
||||||
| .. method:: generator.send(value) | ||||||
|
|
||||||
| "Sends" a value into the generator function: the *value* argument becomes | ||||||
| the result of the current yield expression. | ||||||
|
|
||||||
| Otherwise, this method behaves like :meth:`~generator.__next__`: it resumes | ||||||
| the underlying function and either returns the next yielded value or raises | ||||||
| :exc:`StopIteration`. | ||||||
|
|
||||||
| When :meth:`send` is called to start the generator, it must be called | ||||||
| with :const:`None` as the argument, because there is no current yield | ||||||
| expression that could receive the value. | ||||||
|
|
||||||
|
|
||||||
| .. method:: generator.throw(value) | ||||||
| generator.throw(type[, value[, traceback]]) | ||||||
|
|
||||||
| Raises an exception at the point where the generator is currently suspended. | ||||||
|
|
||||||
| Otherwise, this method behaves like :meth:`~generator.__next__`: it resumes | ||||||
| the underlying function and either returns the next yielded value or raises | ||||||
| :exc:`StopIteration`. | ||||||
| If the generator function does not catch the passed-in exception, or | ||||||
| raises a different exception, then that exception propagates to the caller. | ||||||
|
|
||||||
| When :meth:`throw` is called to start the generator, the generator | ||||||
| immediately exits (that is, subsequent calls to :meth:`~generator.__next__` | ||||||
| will raise :exc:`StopIteration`) and the thrown exception is propagated to | ||||||
| :meth:`throw`'s caller. | ||||||
|
|
||||||
| In typical use, this is called with a single argument, an exception instance, | ||||||
| similar to the way the :keyword:`raise` keyword is used. | ||||||
|
|
||||||
| For backwards compatibility, however, the second signature is | ||||||
| supported, following a convention from older versions of Python. | ||||||
| The *type* argument should be an exception class, and *value* | ||||||
| should be an exception instance. If the *value* is not provided, the | ||||||
| *type* constructor is called to get an instance. If *traceback* | ||||||
| is provided, it is set on the exception, otherwise any existing | ||||||
| :attr:`~BaseException.__traceback__` attribute stored in *value* may | ||||||
| be cleared. | ||||||
|
|
||||||
| .. versionchanged:: 3.12 | ||||||
|
|
||||||
| The second signature \(type\[, value\[, traceback\]\]\) is deprecated and | ||||||
| may be removed in a future version of Python. | ||||||
|
|
||||||
| .. index:: pair: exception; GeneratorExit | ||||||
|
|
||||||
| .. method:: generator.close() | ||||||
|
|
||||||
| Raises a :exc:`GeneratorExit` exception at the point where the generator | ||||||
| function is currently suspended (equivalent to calling ``throw(GeneratorExit)``). | ||||||
|
|
||||||
| If the generator function has already exited (due to an exception or | ||||||
| normal return), or raises :exc:`GeneratorExit` (by not catching the | ||||||
| exception), :meth:`close` returns :const:`None`. | ||||||
| If the generator yields a value, a :exc:`RuntimeError` is raised. | ||||||
| If the generator raises any other exception, it is propagated to the caller. | ||||||
| If a generator returns a value upon being closed, that value is returned | ||||||
| by :meth:`close`. | ||||||
|
|
||||||
| When a generator iterator is garbage collected before it has exited, | ||||||
| :meth:`~generator.close` is called automatically. | ||||||
|
|
||||||
| .. versionchanged:: 3.13 | ||||||
|
|
||||||
| If a generator returns a value upon being closed, the value is returned | ||||||
| by :meth:`close`. | ||||||
| Previously, it returned ``None``. | ||||||
|
|
||||||
|
|
||||||
| Calling any of the generator methods (:meth:`~generator.__next__`, | ||||||
| :meth:`~generator.send`, :meth:`~generator.throw`, :meth:`~generator.close`) | ||||||
| while one of these methods is already executing | ||||||
| raises a :exc:`ValueError` exception. | ||||||
|
|
||||||
|
|
||||||
| .. index:: pair: object; asynchronous-generator | ||||||
| .. _asynchronous-generator-methods: | ||||||
|
|
||||||
| Asynchronous generator-iterators | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||||||
|
|
||||||
| This subsection describes the methods of an asynchronous generator iterator, | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. An expanded introduction would be nice here, too. Although that can be done in a follow up. |
||||||
| which are used to control the execution of an asynchronous generator function. | ||||||
|
|
||||||
|
|
||||||
| .. index:: pair: exception; StopAsyncIteration | ||||||
|
|
||||||
| .. method:: agen.__anext__() | ||||||
| :async: | ||||||
|
|
||||||
| Returns an :term:`awaitable` which when run starts to execute the | ||||||
| asynchronous generator function or resumes it at the | ||||||
| :ref:`yield expression <yieldexpr>` where the function is currently suspended. | ||||||
| When an asynchronous generator function is resumed with an | ||||||
| :meth:`~agen.__anext__` method, the current yield expression always | ||||||
| evaluates to :const:`None` in the returned awaitable, which when run will | ||||||
| continue to the next yield expression. | ||||||
| The value of the expression after the :keyword:`yield` keyword is the value | ||||||
| of the :exc:`StopIteration` exception raised by the completing coroutine. | ||||||
| If the asynchronous generator exits without yielding another value, the | ||||||
| awaitable instead raises a :exc:`StopAsyncIteration` exception, | ||||||
| signalling that the asynchronous iteration has completed. | ||||||
|
|
||||||
| This method is normally called implicitly by a :keyword:`async for` loop, | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| or by the built-in :func:`anext` function. | ||||||
|
|
||||||
|
|
||||||
| Asynchronous generator-iterators have a few more methods than generic | ||||||
| asynchronous iterators, which can be used to control the execution of | ||||||
| the underlying generator function: | ||||||
|
|
||||||
| .. method:: agen.asend(value) | ||||||
| :async: | ||||||
|
|
||||||
| Returns an awaitable which, when run, "sends" a value into the underlying | ||||||
| asynchronous generator function: the *value* argument becomes | ||||||
| the result of the current yield expression. | ||||||
|
|
||||||
| Otherwise, this method behaves like :meth:`~agen.__anext__`: when the | ||||||
| returned awaitable runs, it resumes the underlying function and either | ||||||
| returns the next yielded value as the value of the raised | ||||||
| :exc:`StopIteration`, or raises :exc:`StopAsyncIteration`. | ||||||
|
|
||||||
| :meth:`asend` is called to start the asynchronous | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
lost during the refactor. |
||||||
| generator, it must be called with :const:`None` as the argument, | ||||||
| because there is no yield expression that could receive the value. | ||||||
|
|
||||||
|
|
||||||
| .. method:: agen.athrow(value) | ||||||
| agen.athrow(type[, value[, traceback]]) | ||||||
| :async: | ||||||
|
|
||||||
| Returns an awaitable that, when run, raises an exception at the point where | ||||||
| the underlying asynchronous generator function is currently suspended. | ||||||
|
|
||||||
| Otherwise, this method behaves like :meth:`~agen.__anext__`: when the | ||||||
| returned awaitable runs, it resumes the underlying function (with an | ||||||
| exception raised) and either returns the next yielded value as the value of | ||||||
| the raised :exc:`StopIteration`, or raises :exc:`StopAsyncIteration`. | ||||||
| If the underlying function does not catch the passed-in exception, or | ||||||
| raises a different exception, then when the awaitable is run, that | ||||||
| exception propagates to the caller of the awaitable. | ||||||
|
|
||||||
| When :meth:`~agen.athrow` is called to start the generator, the generator | ||||||
| exits when the awaitable runs (that is, subsequent results from | ||||||
| :meth:`~agen.__anext__` will raise :exc:`StopAsyncIteration` when run) | ||||||
| and the thrown exception is propagated to the awaitable's caller. | ||||||
|
|
||||||
| In typical use, this is called with a single argument, an exception instance, | ||||||
| similar to the way the :keyword:`raise` keyword is used. | ||||||
|
|
||||||
| For backwards compatibility, however, the second signature is | ||||||
| supported. | ||||||
| An exception instance is created from three arguments in the same way as in | ||||||
| :meth:`generator.throw` | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| .. versionchanged:: 3.12 | ||||||
|
|
||||||
| The second signature \(type\[, value\[, traceback\]\]\) is deprecated and | ||||||
| may be removed in a future version of Python. | ||||||
|
|
||||||
|
|
||||||
| .. index:: pair: exception; GeneratorExit | ||||||
|
|
||||||
| .. method:: agen.aclose() | ||||||
| :async: | ||||||
|
|
||||||
| Returns an awaitable that when run will throw a :exc:`GeneratorExit` into | ||||||
| the underlying asynchronous generator function at the point where it is | ||||||
| currently suspended (equivalent to calling ``athrow(GeneratorExit)``). | ||||||
|
|
||||||
| If the asynchronous generator function then exits gracefully, is already | ||||||
| closed, or raises :exc:`GeneratorExit` (by not catching the exception), | ||||||
| then the returned awaitable will raise a :exc:`StopIteration` exception. | ||||||
| Any further awaitables returned by subsequent calls to the asynchronous | ||||||
| generator will raise a :exc:`StopAsyncIteration` exception. | ||||||
|
|
||||||
| If the asynchronous generator yields a value, a :exc:`RuntimeError` is | ||||||
| raised by the awaitable. | ||||||
| If the asynchronous generator raises any other exception, that exception | ||||||
| is propagated to the caller of the awaitable. | ||||||
|
|
||||||
| If the asynchronous generator has already exited due to an exception or | ||||||
| normal exit, then further calls to :meth:`aclose` will return an awaitable | ||||||
| that does nothing. | ||||||
|
|
||||||
|
|
||||||
| .. _typesseq: | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This unfortunately isn't helping #126052.