Python 3.x: Test if generator has elements remaining

后端 未结 4 1245
旧巷少年郎
旧巷少年郎 2021-02-04 00:56

When I use a generator in a for loop, it seems to \"know\", when there are no more elements yielded. Now, I have to use a generator WITHOUT a for loop, and use next

4条回答
  •  Happy的楠姐
    2021-02-04 01:31

    It is not possible to know beforehand about end-of-iterator in the general case, because arbitrary code may have to run to decide about the end. Buffering elements could help revealing things at costs - but this is rarely useful.

    In practice the question arises when one wants to take only one or few elements from an iterator for now, but does not want to write that ugly exception handling code (as indicated in the question). Indeed it is non-pythonic to put the concept "StopIteration" into normal application code. And exception handling on python level is rather time-consuming - particularly when it's just about taking one element.

    The pythonic way to handle those situations best is either using for .. break [.. else] like:

    for x in iterator:
        do_something(x)
        break
    else:
        it_was_exhausted()
    

    or using the builtin next() function with default like

    x = next(iterator, default_value)
    

    or using iterator helpers e.g. from itertools module for rewiring things like:

    max_3_elements = list(itertools.islice(iterator, 3))
    

    Some iterators however expose a "length hint" (PEP424) :

    >>> gen = iter(range(3))
    >>> gen.__length_hint__()
    3
    >>> next(gen)
    0
    >>> gen.__length_hint__()
    2
    

    Note: iterator.__next__() should not be used by normal app code. That's why they renamed it from iterator.next() in Python2. And using next() without default is not much better ...

提交回复
热议问题