Skip to content

Commit be36e06

Browse files
authored
bpo-45250: fix docs regarding __iter__ and iterators being inconsistently required by CPython (GH-29170)
It is now considered a historical accident that e.g. `for` loops and the `iter()` built-in function do not require the iterators they work with to define `__iter__`, only `__next__`.
1 parent 4c61691 commit be36e06

File tree

7 files changed

+51
-47
lines changed

7 files changed

+51
-47
lines changed

Doc/c-api/iter.rst

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ There are two functions specifically for working with iterators.
99

1010
.. c:function:: int PyIter_Check(PyObject *o)
1111
12-
Return non-zero if the object *o* supports the iterator protocol, and ``0``
13-
otherwise. This function always succeeds.
12+
Return non-zero if the object *o* can be safely passed to
13+
:c:func:`PyIter_Next`, and ``0`` otherwise. This function always succeeds.
1414
1515
.. c:function:: int PyAIter_Check(PyObject *o)
1616
@@ -21,10 +21,11 @@ There are two functions specifically for working with iterators.
2121
2222
.. c:function:: PyObject* PyIter_Next(PyObject *o)
2323
24-
Return the next value from the iteration *o*. The object must be an iterator
25-
(it is up to the caller to check this). If there are no remaining values,
26-
returns ``NULL`` with no exception set. If an error occurs while retrieving
27-
the item, returns ``NULL`` and passes along the exception.
24+
Return the next value from the iterator *o*. The object must be an iterator
25+
according to :c:func:`PyIter_Check` (it is up to the caller to check this).
26+
If there are no remaining values, returns ``NULL`` with no exception set.
27+
If an error occurs while retrieving the item, returns ``NULL`` and passes
28+
along the exception.
2829
2930
To write a loop which iterates over an iterator, the C code should look
3031
something like this::

Doc/c-api/typeobj.rst

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1521,9 +1521,9 @@ and :c:type:`PyType_Type` effectively act as defaults.)
15211521

15221522
.. c:member:: getiterfunc PyTypeObject.tp_iter
15231523
1524-
An optional pointer to a function that returns an iterator for the object. Its
1525-
presence normally signals that the instances of this type are iterable (although
1526-
sequences may be iterable without this function).
1524+
An optional pointer to a function that returns an :term:`iterator` for the
1525+
object. Its presence normally signals that the instances of this type are
1526+
:term:`iterable` (although sequences may be iterable without this function).
15271527

15281528
This function has the same signature as :c:func:`PyObject_GetIter`::
15291529

@@ -1536,8 +1536,8 @@ and :c:type:`PyType_Type` effectively act as defaults.)
15361536

15371537
.. c:member:: iternextfunc PyTypeObject.tp_iternext
15381538
1539-
An optional pointer to a function that returns the next item in an iterator.
1540-
The signature is::
1539+
An optional pointer to a function that returns the next item in an
1540+
:term:`iterator`. The signature is::
15411541

15421542
PyObject *tp_iternext(PyObject *self);
15431543

@@ -2429,8 +2429,8 @@ Async Object Structures
24292429

24302430
PyObject *am_await(PyObject *self);
24312431

2432-
The returned object must be an iterator, i.e. :c:func:`PyIter_Check` must
2433-
return ``1`` for it.
2432+
The returned object must be an :term:`iterator`, i.e. :c:func:`PyIter_Check`
2433+
must return ``1`` for it.
24342434

24352435
This slot may be set to ``NULL`` if an object is not an :term:`awaitable`.
24362436

Doc/glossary.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,11 @@ Glossary
659659

660660
More information can be found in :ref:`typeiter`.
661661

662+
.. impl-detail::
663+
664+
CPython does not consistently apply the requirement that an iterator
665+
define :meth:`__iter__`.
666+
662667
key function
663668
A key function or collation function is a callable that returns a value
664669
used for sorting or ordering. For example, :func:`locale.strxfrm` is

Doc/library/functions.rst

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,6 @@ are always available. They are listed here in alphabetical order.
6666
Return an :term:`asynchronous iterator` for an :term:`asynchronous iterable`.
6767
Equivalent to calling ``x.__aiter__()``.
6868

69-
``aiter(x)`` itself has an ``__aiter__()`` method that returns ``x``,
70-
so ``aiter(aiter(x))`` is the same as ``aiter(x)``.
71-
7269
Note: Unlike :func:`iter`, :func:`aiter` has no 2-argument variant.
7370

7471
.. versionadded:: 3.10
@@ -929,8 +926,8 @@ are always available. They are listed here in alphabetical order.
929926
Return an :term:`iterator` object. The first argument is interpreted very
930927
differently depending on the presence of the second argument. Without a
931928
second argument, *object* must be a collection object which supports the
932-
iteration protocol (the :meth:`__iter__` method), or it must support the
933-
sequence protocol (the :meth:`__getitem__` method with integer arguments
929+
:term:`iterable` protocol (the :meth:`__iter__` method), or it must support
930+
the sequence protocol (the :meth:`__getitem__` method with integer arguments
934931
starting at ``0``). If it does not support either of those protocols,
935932
:exc:`TypeError` is raised. If the second argument, *sentinel*, is given,
936933
then *object* must be a callable object. The iterator created in this case
@@ -1060,7 +1057,7 @@ are always available. They are listed here in alphabetical order.
10601057

10611058
.. function:: next(iterator[, default])
10621059

1063-
Retrieve the next item from the *iterator* by calling its
1060+
Retrieve the next item from the :term:`iterator` by calling its
10641061
:meth:`~iterator.__next__` method. If *default* is given, it is returned
10651062
if the iterator is exhausted, otherwise :exc:`StopIteration` is raised.
10661063

Doc/library/stdtypes.rst

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -810,40 +810,41 @@ using two distinct methods; these are used to allow user-defined classes to
810810
support iteration. Sequences, described below in more detail, always support
811811
the iteration methods.
812812

813-
One method needs to be defined for container objects to provide iteration
813+
One method needs to be defined for container objects to provide :term:`iterable`
814814
support:
815815

816816
.. XXX duplicated in reference/datamodel!
817817
818818
.. method:: container.__iter__()
819819

820-
Return an iterator object. The object is required to support the iterator
821-
protocol described below. If a container supports different types of
822-
iteration, additional methods can be provided to specifically request
820+
Return an :term:`iterator` object. The object is required to support the
821+
iterator protocol described below. If a container supports different types
822+
of iteration, additional methods can be provided to specifically request
823823
iterators for those iteration types. (An example of an object supporting
824824
multiple forms of iteration would be a tree structure which supports both
825825
breadth-first and depth-first traversal.) This method corresponds to the
826-
:c:member:`~PyTypeObject.tp_iter` slot of the type structure for Python objects in the Python/C
827-
API.
826+
:c:member:`~PyTypeObject.tp_iter` slot of the type structure for Python
827+
objects in the Python/C API.
828828

829829
The iterator objects themselves are required to support the following two
830830
methods, which together form the :dfn:`iterator protocol`:
831831

832832

833833
.. method:: iterator.__iter__()
834834

835-
Return the iterator object itself. This is required to allow both containers
836-
and iterators to be used with the :keyword:`for` and :keyword:`in` statements.
837-
This method corresponds to the :c:member:`~PyTypeObject.tp_iter` slot of the type structure for
838-
Python objects in the Python/C API.
835+
Return the :term:`iterator` object itself. This is required to allow both
836+
containers and iterators to be used with the :keyword:`for` and
837+
:keyword:`in` statements. This method corresponds to the
838+
:c:member:`~PyTypeObject.tp_iter` slot of the type structure for Python
839+
objects in the Python/C API.
839840

840841

841842
.. method:: iterator.__next__()
842843

843-
Return the next item from the container. If there are no further items, raise
844-
the :exc:`StopIteration` exception. This method corresponds to the
845-
:c:member:`~PyTypeObject.tp_iternext` slot of the type structure for Python objects in the
846-
Python/C API.
844+
Return the next item from the :term:`iterator`. If there are no further
845+
items, raise the :exc:`StopIteration` exception. This method corresponds to
846+
the :c:member:`~PyTypeObject.tp_iternext` slot of the type structure for
847+
Python objects in the Python/C API.
847848

848849
Python defines several iterator objects to support iteration over general and
849850
specific sequence types, dictionaries, and other more specialized forms. The

Doc/reference/datamodel.rst

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -648,13 +648,13 @@ Callable types
648648

649649
A function or method which uses the :keyword:`yield` statement (see section
650650
:ref:`yield`) is called a :dfn:`generator function`. Such a function, when
651-
called, always returns an iterator object which can be used to execute the
652-
body of the function: calling the iterator's :meth:`iterator.__next__`
653-
method will cause the function to execute until it provides a value
654-
using the :keyword:`!yield` statement. When the function executes a
655-
:keyword:`return` statement or falls off the end, a :exc:`StopIteration`
656-
exception is raised and the iterator will have reached the end of the set of
657-
values to be returned.
651+
called, always returns an :term:`iterator` object which can be used to
652+
execute the body of the function: calling the iterator's
653+
:meth:`iterator.__next__` method will cause the function to execute until
654+
it provides a value using the :keyword:`!yield` statement. When the
655+
function executes a :keyword:`return` statement or falls off the end, a
656+
:exc:`StopIteration` exception is raised and the iterator will have
657+
reached the end of the set of values to be returned.
658658

659659
Coroutine functions
660660
.. index::
@@ -674,7 +674,7 @@ Callable types
674674
A function or method which is defined using :keyword:`async def` and
675675
which uses the :keyword:`yield` statement is called a
676676
:dfn:`asynchronous generator function`. Such a function, when called,
677-
returns an asynchronous iterator object which can be used in an
677+
returns an :term:`asynchronous iterator` object which can be used in an
678678
:keyword:`async for` statement to execute the body of the function.
679679

680680
Calling the asynchronous iterator's :meth:`aiterator.__anext__` method
@@ -2499,12 +2499,10 @@ through the object's keys; for sequences, it should iterate through the values.
24992499

25002500
.. method:: object.__iter__(self)
25012501

2502-
This method is called when an iterator is required for a container. This method
2503-
should return a new iterator object that can iterate over all the objects in the
2504-
container. For mappings, it should iterate over the keys of the container.
2505-
2506-
Iterator objects also need to implement this method; they are required to return
2507-
themselves. For more information on iterator objects, see :ref:`typeiter`.
2502+
This method is called when an :term:`iterator` is required for a container.
2503+
This method should return a new iterator object that can iterate over all the
2504+
objects in the container. For mappings, it should iterate over the keys of
2505+
the container.
25082506

25092507

25102508
.. method:: object.__reversed__(self)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Update the documentation to note that CPython does not consistently
2+
require iterators to define ``__iter__``.

0 commit comments

Comments
 (0)