Cómo probar si PyObject tiene un iterador

8

Estoy implementando una función C como una extensión para Python. En el interior abstract.h, encontré lo siguiente:

/* ==== Iterators ================================================ */

/* Takes an object and returns an iterator for it.
   This is typically a new iterator but if the argument is an iterator, this
   returns itself. */
PyAPI_FUNC(PyObject *) PyObject_GetIter(PyObject *);

/* Returns 1 if the object 'obj' provides iterator protocols, and 0 otherwise.

   This function always succeeds. */
PyAPI_FUNC(int) PyIter_Check(PyObject *);

Cuando intento que los iteradores usen PyObject_GetIterobjetos obviamente no iterables como un número, obtengo el error SystemError: <built-in function xxx> returned a result with an error set.

static PyObject *my_method(PyObject *self, PyObject *args) 
{
    PyObject *obj;
    PyArg_ParseTuple(args, "O", &obj)
    //  printf("\ncheck %d",PyIter_Check(obj)); // always 0
    PyObject *iter = PyObject_GetIter(obj); // throws error
    return PyLong_FromLong(0);
}

Me gustaría manejar los errores por mi cuenta. Así que traté de usar PyIter_Checkpara probar si el objeto tiene un iterador. Sin embargo, esta función devolvió 0 para todos los objetos que proporcioné, incluidos los iterables.

Pensé que podría ser causado por la PyAPI_FUNC()macro, pero lo encontré pyport.hy parece que solo está agregando __declspec.

  • ¿Por qué la función PyIter_Checkdevuelve cero para todos los objetos?
thehorseisbrown
fuente

Respuestas:

2

PyIter_Checkes para verificar si un objeto es un iterador, no si puede proporcionar uno. No parece haber un PyIterable_Check.

Además, Python hace cumplir prácticamente la EAFP: dado que cualquier cosa podría generar __iter__un error que genere una excepción, debe verificar si hay un error de PyObject_GetItertodos modos, por lo que el único punto de las *_Checkfunciones es proporcionar comprobaciones de sanidad tempranas (a veces con mejores mensajes de error).

Arenque Davis
fuente
¡Gracias! Súper servicial Voy a estudiar el manejo de excepciones :)
thehorseisbrown
@thehorseisbrown: Aparte de los mensajes de correo electrónico apropiados Py_DECREFpara referencias existentes, por lo general solo puede decir PyObject *const x=Py_Foo(…); if(!x) return 0;.
Davis Herring