diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 0b6a1b488fb64f..58aa319907ed74 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -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 `. +Python's :term:`generators ` -- or more precisely, +:term:`generator functions ` and +:term:`generator iterators ` -- provide a convenient way +to implement the iterator protocol. + +A function that contains one or more :ref:`yield expressions ` +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 ` +(for example, they have the same attributes), except that calling a generator +function returns a :ref:`generator iterator `:: + + >>> count_to_three() + + +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): + ... yield 'three of clubs' + ... yield 'ace of hearts' + + >>> list(CardDeck()) + ... ['three of clubs', 'ace of hearts'] + + +.. index:: pair: object; generator +.. _generator-methods: + +Generator iterators +^^^^^^^^^^^^^^^^^^^ + +Generator iterators implement the +:ref:`iterator protocol `. +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 ` 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 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This subsection describes the methods of an asynchronous generator iterator, +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 ` 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, + 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 + 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` + + .. 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: diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst index af313f42f9bff6..2e0b6621eb11c8 100644 --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -1179,95 +1179,6 @@ on the right hand side of an assignment statement. The proposal that expanded on :pep:`492` by adding generator capabilities to coroutine functions. -.. index:: pair: object; generator -.. _generator-methods: - -Generator-iterator methods -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -This subsection describes the methods of a generator iterator. They can -be used to control the execution of a generator function. - -Note that calling any of the generator methods below when the generator -is already executing raises a :exc:`ValueError` exception. - -.. index:: pair: exception; StopIteration - - -.. method:: generator.__next__() - - Starts the execution of a generator function or resumes it at the last - executed yield expression. 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 - :token:`~python-grammar:yield_list` is returned to :meth:`__next__`'s - caller. If the generator exits without yielding another value, a - :exc:`StopIteration` exception is raised. - - This method is normally called implicitly, e.g. by a :keyword:`for` loop, or - by the built-in :func:`next` function. - - -.. method:: generator.send(value) - - Resumes the execution and "sends" a value into the generator function. The - *value* argument becomes the result of the current yield expression. The - :meth:`send` method returns the next value yielded by the generator, or - raises :exc:`StopIteration` if the generator exits without yielding another - value. When :meth:`send` is called to start the generator, it must be called - with :const:`None` as the argument, because there is no 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 was paused, - and returns the next value yielded by the generator function. If the generator - exits without yielding another value, a :exc:`StopIteration` exception is - raised. If the generator function does not catch the passed-in exception, or - raises a different exception, then that exception propagates to the caller. - - In typical use, this is called with a single 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 was paused (equivalent to calling ``throw(GeneratorExit)``). - The exception is raised by the yield expression where the generator was paused. - If the generator function catches the exception and returns a - value, this value is returned from :meth:`close`. If the generator function - is already closed, 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 the generator has already - exited due to an exception or normal exit, :meth:`close` returns - :const:`None` and has no other effect. - - .. versionchanged:: 3.13 - - If a generator returns a value upon being closed, the value is returned - by :meth:`close`. - .. index:: single: yield; examples Examples @@ -1367,90 +1278,6 @@ of a *finalizer* method see the implementation of The expression ``yield from `` is a syntax error when used in an asynchronous generator function. -.. index:: pair: object; asynchronous-generator -.. _asynchronous-generator-methods: - -Asynchronous generator-iterator methods -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -This subsection describes the methods of an asynchronous generator iterator, -which are used to control the execution of a generator function. - - -.. index:: pair: exception; StopAsyncIteration - -.. method:: agen.__anext__() - :async: - - Returns an awaitable which when run starts to execute the asynchronous - generator or resumes it at the last executed yield expression. 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 :token:`~python-grammar:yield_list` of the - yield expression 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. - - -.. method:: agen.asend(value) - :async: - - Returns an awaitable which when run resumes the execution of the - asynchronous generator. As with the :meth:`~generator.send` method for a - generator, this "sends" a value into the asynchronous generator function, - and the *value* argument becomes the result of the current yield expression. - The awaitable returned by the :meth:`asend` method will return the next - value yielded by the generator as the value of the raised - :exc:`StopIteration`, or raises :exc:`StopAsyncIteration` if the - asynchronous generator exits without yielding another value. When - :meth:`asend` is called to start the asynchronous - 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 raises an exception of type ``type`` at the point - where the asynchronous generator was paused, and returns the next value - yielded by the generator function as the value of the raised - :exc:`StopIteration` exception. If the asynchronous generator exits - without yielding another value, a :exc:`StopAsyncIteration` exception is - raised by the awaitable. - If the generator 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. - - .. 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 asynchronous generator function at the point where it was paused. - 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, - it 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. - .. _primaries: Primaries diff --git a/Doc/tools/removed-ids.txt b/Doc/tools/removed-ids.txt index 7796d15f4d2735..91340eb75e5748 100644 --- a/Doc/tools/removed-ids.txt +++ b/Doc/tools/removed-ids.txt @@ -59,3 +59,17 @@ using/windows.html: return-codes using/windows.html: the-full-installer-deprecated using/windows.html: virtual-environments using/windows.html: windows-full + +# Moved to library/stdtypes: +reference/expressions.html: agen.__anext__ +reference/expressions.html: agen.aclose +reference/expressions.html: agen.asend +reference/expressions.html: agen.athrow +reference/expressions.html: asynchronous-generator-iterator-methods +reference/expressions.html: asynchronous-generator-methods +reference/expressions.html: generator-iterator-methods +reference/expressions.html: generator-methods +reference/expressions.html: generator.__next__ +reference/expressions.html: generator.close +reference/expressions.html: generator.send +reference/expressions.html: generator.throw