Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I check if an object is an iterator in Python?

I can check for a next() method, but is that enough? Is there an ideomatic way?

like image 494
Juanjo Conti Avatar asked Jun 11 '10 14:06

Juanjo Conti


People also ask

What objects are iterators in Python?

An iterator is an object that contains a countable number of values. An iterator is an object that can be iterated upon, meaning that you can traverse through all the values. Technically, in Python, an iterator is an object which implements the iterator protocol, which consist of the methods __iter__() and __next__() .

What does __ ITER __ do in Python?

The __iter__() function returns an iterator for the given object (array, set, tuple, etc. or custom objects). It creates an object that can be accessed one element at a time using __next__() function, which generally comes in handy when dealing with loops.

What is the type of iterator Python?

An iterator in Python is an object that contains a countable number of elements that can be iterated upon. In simpler words, we can say that Iterators are objects that allow you to traverse through all the elements of a collection and return one element at a time.


2 Answers

In Python 2.6 or better, the designed-in idiom for such behavioral checks is a "membership check" with the abstract base class in the collections module of the standard library:

>>> import collections >>> isinstance('ciao', collections.Iterable) True >>> isinstance(23, collections.Iterable) False >>> isinstance(xrange(23), collections.Iterable) True 

Indeed, this kind of checks is the prime design reason for the new abstract base classes (a second important one is to provide "mixin functionality" in some cases, which is why they're ABCs rather than just interfaces -- but that doesn't apply to collections.Iterable, it exists strictly to allow such checks with isinstance or issubclass). ABCs allow classes that don't actually inherit from them to be "registered" as subclasses anyway, so that such classes can be "subclasses" of the ABC for such checks; and, they can internally perform all needed checks for special methods (__iter__ in this case), so you don't have to.

If you're stuck with older releases of Python, "it's better to ask forgiveness than permission":

def isiterable(x):   try: iter(x)   except TypeError: return False   else: return True 

but that's not as fast and concise as the new approach.

Note that for this special case you'll often want to special-case strings (which are iterable but most application contexts want to treat as "scalars" anyway). Whatever approach you're using to check iterableness, if you need such special casing just prepend a check for isinstance(x, basestring) -- for example:

def reallyiterable(x):   return not isinstance(x, basestring) and isinstance(x, collections.Iterable) 

Edit: as pointed out in a comment, the question focuses on whether an object is an iter***ator*** rather than whether it's iter***able*** (all iterators are iterable, but not vice versa -- not all iterables are iterators). isinstance(x, collections.Iterator) is the perfectly analogous way to check for that condition specifically.

like image 152
Alex Martelli Avatar answered Oct 03 '22 17:10

Alex Martelli


An object is iterable if it implements the iterator protocol.
You could check the presence of __iter__() method with:

hasattr(object,'__iter__') 

in Python 2.x this approach misses str objects and other built-in sequence types like unicode, xrange, buffer. It works in Python 3.

Another way is to test it with iter method :

try:    iter(object) except TypeError:    #not iterable 
like image 27
systempuntoout Avatar answered Oct 03 '22 16:10

systempuntoout