Is there a method like isiterable
? The only solution I have found so far is to call
hasattr(myObj, '__iter__')
But I am not sure how fool-proof this is.
Is there a method like isiterable
? The only solution I have found so far is to call
hasattr(myObj, '__iter__')
But I am not sure how fool-proof this is.
Duck typing
Type checking
Use the Abstract Base Classes. They need at least Python 2.6 and work only for new-style classes.
However,
iter()
is a bit more reliable as described by the documentation:This isn't sufficient: the object returned by
__iter__
must implement the iteration protocol (i.e.next
method). See the relevant section in the documentation.In Python, a good practice is to "try and see" instead of "checking".
In Python <= 2.5, you can't and shouldn't - iterable was an "informal" interface.
But since Python 2.6 and 3.0 you can leverage the new ABC (abstract base class) infrastructure along with some builtin ABCs which are available in the collections module:
Now, whether this is desirable or actually works, is just a matter of conventions. As you can see, you can register a non-iterable object as Iterable - and it will raise an exception at runtime. Hence, isinstance acquires a "new" meaning - it just checks for "declared" type compatibility, which is a good way to go in Python.
On the other hand, if your object does not satisfy the interface you need, what are you going to do? Take the following example:
If the object doesn't satisfy what you expect, you just throw a TypeError, but if the proper ABC has been registered, your check is unuseful. On the contrary, if the
__iter__
method is available Python will automatically recognize object of that class as being Iterable.So, if you just expect an iterable, iterate over it and forget it. On the other hand, if you need to do different things depending on input type, you might find the ABC infrastructure pretty useful.
The easiest way, respecting the Python's duck typing, is to catch the error (Python knows perfectly what does it expect from an object to become an iterator):
Notes:
__iter__
has been implemented, if the exception type is the same: anyway you will not be able to iterate the object.I think I understand your concern: How does
callable
exists as a check if I could also rely on duck typing to raise anAttributeError
if__call__
is not defined for my object, but that's not the case for iterable checking?I don't know the answer, but you can either implement the function I (and other users) gave, or just catch the exception in your code (your implementation in that part will be like the function I wrote - just ensure you isolate the iterator creation from the rest of the code so you can capture the exception and distinguish it from another
TypeError
.I often find convenient, inside my scripts, to define an
iterable
function. (Now incorporates Alfe's suggested simplification):so you can test if any object is iterable in the very readable form
as you would do with the
callable
functionEDIT: if you have numpy installed, you can simply do: from
numpy import iterable
, which is simply something likeIf you do not have numpy, you can simply implement this code, or the one above.
The best solution I've found so far:
hasattr(obj, '__contains__')
which basically checks if the object implements the
in
operator.Advantages (none of the other solutions has all three):
__iter__
)Notes: