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
.
PyIter_Check
returning zero for all objects?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 .
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.
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.
'tuple' object is not an iterator.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With