next
is precious to advance an iterator when necessary, without that advancement controlling an explicit for
loop. For example, if you want "the first item in S that's greater than 100", next(x for x in S if x > 100)
will give it to you, no muss, no fuss, no unneeded work (as everything terminates as soon as a suitable x
is located) -- and you get an exception (StopIteration
) if unexpectedly no x
matches the condition. If a no-match is expected and you want None
in that case, next((x for x in S if x > 100), None)
will deliver that. For this specific purpose, it might be clearer to you if next
was actually named first
, but that would betray its much more general use.
Consider, for example, the task of merging multiple sequences (e.g., a union or intersection of sorted sequences -- say, sorted files, where the items are lines). Again, next
is just what the doctor ordered, because none of the sequences can dominate over the others by controlling A "main for
loop". So, assuming for simplicity no duplicates can exist (a condition that's not hard to relax if needed), you keep pairs (currentitem, itsfile)
in a list controlled by heapq
, and the merging becomes easy... but only thanks to the magic of next
to advance the correct file once its item has been used, and that file only.
import heapq
def merge(*theopentextfiles):
theheap = []
for afile in theopentextfiles:
theitem = next(afile, '')
if theitem: theheap.append((theitem, afile))
heapq.heapify(theheap)
while theheap:
theitem, afile = heapq.heappop(theheap)
yielf theitem
theitem = next(afile, '')
if theitem: heapq.heappush(theheap, (theitem, afile))
Just try to do anything anywhere this elegant without next
...!-)
One could go on for a long time, but the two use cases "advance an iterator by one place (without letting it control a whole for
loop)" and "get just the first item from an iterator" account for most important uses of next
.