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

前端 未结 8 1701
天命终不由人
天命终不由人 2020-12-25 10:10

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

相关标签:
8条回答
  • 2020-12-25 10:47

    There is a better method than other answers have suggested.

    In Python we have two kinds of things: Iterable and Iterator. An object is Iterable if it can give you Iterator. It does so when you use iter() on it. An object is Iterator if you can use next() to sequentially browse through its elements. For example, map() returns Iterator and list is Iterable.

    Here are more details.

    Below code illustrates how to check for these types:

    from collections.abc import Iterable, Iterator
    
    r = [1, 2, 3]
    e = map(lambda x:x, r)
    
    print(isinstance(r, Iterator)) # False, because can't apply next
    print(isinstance(e, Iterator)) # True
    print(isinstance(r, Iterable)) # True, because can apply iter()
    print(isinstance(e, Iterable)) # True, note iter() returns self
    
    0 讨论(0)
  • 2020-12-25 10:52

    To be an iterator an object must pass three tests:

    • obj has an __iter__ method
    • obj has a next method (or __next__ in Python 3)
    • obj.__iter__() returns obj

    So, a roll-your-own test would look like:

    def is_iterator(obj):
        if (
                hasattr(obj, '__iter__') and
                hasattr(obj, 'next') and      # or __next__ in Python 3
                callable(obj.__iter__) and
                obj.__iter__() is obj
            ):
            return True
        else:
            return False
    
    0 讨论(0)
  • 2020-12-25 10:54

    answer from python sourcecode doc comments:

    {python install path}/Versions/3.5/lib/python3.5/types.py

    # Iterators in Python aren't a matter of type but of protocol.  A large
    # and changing number of builtin types implement *some* flavor of
    # iterator.  Don't check the type!  Use hasattr to check for both
    # "__iter__" and "__next__" attributes instead.
    
    0 讨论(0)
  • 2020-12-25 11:03

    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
    
    0 讨论(0)
  • 2020-12-25 11:07
    from collections.abc import Iterator
    
    isinstance(object, Iterator)
    
    0 讨论(0)
  • As the question is about Iterator not Iterable and considering usage of iterator, a simplest and pythonic way of doing this

    iterable = [1,2]
    iterator = iter(iterable)
    
    
    def isIterator(obj):
        try:
            next(obj, None)
            return True
        except TypeError:
            return False
    
    >>> isIterator(iterable)
    False
    >>> isIterator(iterator)
    True
    

    Yes. Checking on next() should be enough

    0 讨论(0)
提交回复
热议问题