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