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):
- it is an expression (works as a lambda, as opposed to the try...except variant)
- it is (should be) implemented by all iterables, including strings (as opposed to
__iter__
)
- works on any Python >= 2.5
Notes:
- the Python philosophy of "ask for forgiveness, not permission" doesn't work well when e.g. in a list you have both iterables and non-iterables and you need to treat each element differently according to it's type (treating iterables on try and non-iterables on except would work, but it would look butt-ugly and misleading)
- solutions to this problem which attempt to actually iterate over the object (e.g. [x for x in obj]) to check if it's iterable may induce significant performance penalties for large iterables (especially if you just need the first few elements of the iterable, for example) and should be avoided