xref: /third_party/python/Doc/c-api/iter.rst (revision 7db96d56)
17db96d56Sopenharmony_ci.. highlight:: c
27db96d56Sopenharmony_ci
37db96d56Sopenharmony_ci.. _iterator:
47db96d56Sopenharmony_ci
57db96d56Sopenharmony_ciIterator Protocol
67db96d56Sopenharmony_ci=================
77db96d56Sopenharmony_ci
87db96d56Sopenharmony_ciThere are two functions specifically for working with iterators.
97db96d56Sopenharmony_ci
107db96d56Sopenharmony_ci.. c:function:: int PyIter_Check(PyObject *o)
117db96d56Sopenharmony_ci
127db96d56Sopenharmony_ci   Return non-zero if the object *o* can be safely passed to
137db96d56Sopenharmony_ci   :c:func:`PyIter_Next`, and ``0`` otherwise.  This function always succeeds.
147db96d56Sopenharmony_ci
157db96d56Sopenharmony_ci.. c:function:: int PyAIter_Check(PyObject *o)
167db96d56Sopenharmony_ci
177db96d56Sopenharmony_ci   Return non-zero if the object *o* provides the :class:`AsyncIterator`
187db96d56Sopenharmony_ci   protocol, and ``0`` otherwise.  This function always succeeds.
197db96d56Sopenharmony_ci
207db96d56Sopenharmony_ci   .. versionadded:: 3.10
217db96d56Sopenharmony_ci
227db96d56Sopenharmony_ci.. c:function:: PyObject* PyIter_Next(PyObject *o)
237db96d56Sopenharmony_ci
247db96d56Sopenharmony_ci   Return the next value from the iterator *o*.  The object must be an iterator
257db96d56Sopenharmony_ci   according to :c:func:`PyIter_Check` (it is up to the caller to check this).
267db96d56Sopenharmony_ci   If there are no remaining values, returns ``NULL`` with no exception set.
277db96d56Sopenharmony_ci   If an error occurs while retrieving the item, returns ``NULL`` and passes
287db96d56Sopenharmony_ci   along the exception.
297db96d56Sopenharmony_ci
307db96d56Sopenharmony_ciTo write a loop which iterates over an iterator, the C code should look
317db96d56Sopenharmony_cisomething like this::
327db96d56Sopenharmony_ci
337db96d56Sopenharmony_ci   PyObject *iterator = PyObject_GetIter(obj);
347db96d56Sopenharmony_ci   PyObject *item;
357db96d56Sopenharmony_ci
367db96d56Sopenharmony_ci   if (iterator == NULL) {
377db96d56Sopenharmony_ci       /* propagate error */
387db96d56Sopenharmony_ci   }
397db96d56Sopenharmony_ci
407db96d56Sopenharmony_ci   while ((item = PyIter_Next(iterator))) {
417db96d56Sopenharmony_ci       /* do something with item */
427db96d56Sopenharmony_ci       ...
437db96d56Sopenharmony_ci       /* release reference when done */
447db96d56Sopenharmony_ci       Py_DECREF(item);
457db96d56Sopenharmony_ci   }
467db96d56Sopenharmony_ci
477db96d56Sopenharmony_ci   Py_DECREF(iterator);
487db96d56Sopenharmony_ci
497db96d56Sopenharmony_ci   if (PyErr_Occurred()) {
507db96d56Sopenharmony_ci       /* propagate error */
517db96d56Sopenharmony_ci   }
527db96d56Sopenharmony_ci   else {
537db96d56Sopenharmony_ci       /* continue doing useful work */
547db96d56Sopenharmony_ci   }
557db96d56Sopenharmony_ci
567db96d56Sopenharmony_ci
577db96d56Sopenharmony_ci.. c:type:: PySendResult
587db96d56Sopenharmony_ci
597db96d56Sopenharmony_ci   The enum value used to represent different results of :c:func:`PyIter_Send`.
607db96d56Sopenharmony_ci
617db96d56Sopenharmony_ci   .. versionadded:: 3.10
627db96d56Sopenharmony_ci
637db96d56Sopenharmony_ci
647db96d56Sopenharmony_ci.. c:function:: PySendResult PyIter_Send(PyObject *iter, PyObject *arg, PyObject **presult)
657db96d56Sopenharmony_ci
667db96d56Sopenharmony_ci   Sends the *arg* value into the iterator *iter*. Returns:
677db96d56Sopenharmony_ci
687db96d56Sopenharmony_ci   - ``PYGEN_RETURN`` if iterator returns. Return value is returned via *presult*.
697db96d56Sopenharmony_ci   - ``PYGEN_NEXT`` if iterator yields. Yielded value is returned via *presult*.
707db96d56Sopenharmony_ci   - ``PYGEN_ERROR`` if iterator has raised and exception. *presult* is set to ``NULL``.
717db96d56Sopenharmony_ci
727db96d56Sopenharmony_ci   .. versionadded:: 3.10
73