In Python, how do I determine if an object is iterable?

前端 未结 21 2224
太阳男子
太阳男子 2020-11-22 00:35

Is there a method like isiterable? The only solution I have found so far is to call

hasattr(myObj, \'__iter__\')

But I am not

21条回答
  •  栀梦
    栀梦 (楼主)
    2020-11-22 01:00

    def is_iterable(x):
        try:
            0 in x
        except TypeError:
            return False
        else:
            return True
    

    This will say yes to all manner of iterable objects, but it will say no to strings in Python 2. (That's what I want for example when a recursive function could take a string or a container of strings. In that situation, asking forgiveness may lead to obfuscode, and it's better to ask permission first.)

    import numpy
    
    class Yes:
        def __iter__(self):
            yield 1;
            yield 2;
            yield 3;
    
    class No:
        pass
    
    class Nope:
        def __iter__(self):
            return 'nonsense'
    
    assert is_iterable(Yes())
    assert is_iterable(range(3))
    assert is_iterable((1,2,3))   # tuple
    assert is_iterable([1,2,3])   # list
    assert is_iterable({1,2,3})   # set
    assert is_iterable({1:'one', 2:'two', 3:'three'})   # dictionary
    assert is_iterable(numpy.array([1,2,3]))
    assert is_iterable(bytearray("not really a string", 'utf-8'))
    
    assert not is_iterable(No())
    assert not is_iterable(Nope())
    assert not is_iterable("string")
    assert not is_iterable(42)
    assert not is_iterable(True)
    assert not is_iterable(None)
    

    Many other strategies here will say yes to strings. Use them if that's what you want.

    import collections
    import numpy
    
    assert isinstance("string", collections.Iterable)
    assert isinstance("string", collections.Sequence)
    assert numpy.iterable("string")
    assert iter("string")
    assert hasattr("string", '__getitem__')
    

    Note: is_iterable() will say yes to strings of type bytes and bytearray.

    • bytes objects in Python 3 are iterable True == is_iterable(b"string") == is_iterable("string".encode('utf-8')) There is no such type in Python 2.
    • bytearray objects in Python 2 and 3 are iterable True == is_iterable(bytearray(b"abc"))

    The O.P. hasattr(x, '__iter__') approach will say yes to strings in Python 3 and no in Python 2 (no matter whether '' or b'' or u''). Thanks to @LuisMasuelli for noticing it will also let you down on a buggy __iter__.

提交回复
热议问题