hasattr(obj, '__iter__') vs collections
Question: I've seen a couple posts recommending `isinstance(obj, collections.Sequence)`
instead of `hasattr(obj, '__iter__')` to determine if something is a list.

[len(object) or hasattr(object,
__iter__)?](http://stackoverflow.com/questions/1763507/lenobject-or-
hasattrobject-iter)

[Python: is not sequence](http://stackoverflow.com/questions/2937114/python-
is-not-sequence)

At first I was excited because testing if an object has `__iter__` always
seemed dirty to me. But after further review this still seems to be the best
solution because none of the `isinstance` tests on `collection` yield the same
results. `collections.Sequence` is close but it returns `True` for strings.

    
    
    hasattr(obj, '__iter__')
        set([]): True
        {}: True
        []: True
        'str': False
        1: False
    
    isinstance(obj, collections.Iterable)
        set([]): True
        {}: True
        []: True
        'str': True
        1: False
    
    isinstance(obj, collections.Iterator)
        set([]): False
        {}: False
        []: False
        'str': False
        1: False
    
    isinstance(obj, collections.Sequence)
        set([]): False
        {}: False
        []: True
        'str': True
        1: False
    

Here is the code I used to generate this:

    
    
    import collections
    
    testObjs = [
        set(),
        dict(),
        list(),
        'str',
        1
    ]
    
    print "hasattr(obj, '__iter__')"
    for obj in testObjs:
        print '    %r: %r' % (obj, hasattr(obj, '__iter__'))
    print
    
    print "isinstance(obj, collections.Iterable)"
    for obj in testObjs:
        print '    %r: %r' % (obj, isinstance(obj, collections.Iterable))
    print
    
    print "isinstance(obj, collections.Iterator)"
    for obj in testObjs:
        print '    %r: %r' % (obj, isinstance(obj, collections.Iterator))
    print
    
    print "isinstance(obj, collections.Sequence)"
    for obj in testObjs:
        print '    %r: %r' % (obj, isinstance(obj, collections.Sequence))
    print
    

Am I missing something or is `hasattr(obj, '__iter__')` still the best option
for testing if something is iterable?

**EDIT:** I am only interested in detecting the builtin types: `dict`, `list`,
and `set`.(**EDIT:** this is foolish :))

**EDIT:** I should have included the use case that got me looking into this. I
have a function that takes an arg that can be a single value or a sequence. So
I want to detect what it is and turn it into a sequence if it's a single value
so I can deal with it as a sequence after that.

    
    
    if hasattr(arg, '__iter__'):
        arg= set(arg)
    else:
        arg= set([arg])
    

One solution to this is just to let it throw an exception if the object cannot
be iterated. But that doesn't work in my use case. Another solution is to use
something like:

    
    
    import collections
    
    def issequenceforme(obj):
        if isinstance(obj, basestring):
            return False
        return isinstance(obj, collections.Sequence)
    

_From:_ [Python: is not
sequence](http://stackoverflow.com/questions/2937114/python-is-not-sequence)

But this requires this function to be defined which makes me not want to use
it.

It looks like `hasattr(arg, '__iter__')` is still the best option.


Answer: The `collections.Iterable` will guarantee the object is iterable or not (like
using `for x in obj`) but checking `__iter__` will not.

A string is a iterable datatype but on Python2.x it doesn't have a `__iter__`
method.

