Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test if PyObject has an iterator

Tags:

python

c

I am implementing a C function as an extension for Python. Inside abstract.h, I found the following:

/* ==== 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 *);

When I try to get iterators using PyObject_GetIter on obviously non-iterable objects like a number, I get the 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);
}

I would like to handle errors on my own. So I tried to use the PyIter_Check to test if the object has an iterator. However, this function returned 0 for all objects I provided, including the iterable ones.

I thought that it might be caused by the PyAPI_FUNC() macro but I found it in pyport.h and it seems to be only adding __declspec.

  • Why is the function PyIter_Check returning zero for all objects?
like image 489
thehorseisbrown Avatar asked Dec 02 '19 17:12

thehorseisbrown


People also ask

How do I know if I have an iterator?

An object is Iterable if it can give you Iterator . It does so when you use iter() on it. An object is Iterator if you can use next() to sequentially browse through its elements. For example, map() returns Iterator and list is Iterable .

How do you check if an object is an iterator in Python?

To check if the object is iterable in Python, use the iter() method. Python iter() is an inbuilt function that returns an iterator for the given object. The iter() method is the most accurate way to check whether an object is iterable and handle a TypeError exception if it isn't.

How do I use an iterator in Python?

Iterator in python is an object that is used to iterate over iterable objects like lists, tuples, dicts, and sets. The iterator object is initialized using the iter() method. It uses the next() method for iteration. next ( __next__ in Python 3) The next method returns the next value for the iterable.

Is tuple an iterator?

'tuple' object is not an iterator.


1 Answers

PyIter_Check is for checking whether an object is an iterator, not whether it can provide one. There doesn’t appear to be a PyIterable_Check.

Moreover, Python pretty much enforces EAFP: since anything could provide an __iter__ that raises an exception, you have to check for an error from PyObject_GetIter anyway, so the only point of the *_Check functions is to provide early sanity checks (sometimes with better error messages).

like image 183
Davis Herring Avatar answered Dec 15 '22 12:12

Davis Herring