Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Nested for loops or "next" statement

I'm a rookie hobbyist and I nest for loops when I write python, like so:

dict = {
    key1: {subkey/value1: value2} 
    ... 
    keyn: {subkeyn/valuen: valuen+1}
    }

for key in dict:
    for subkey/value in key:
       do it to it

I'm aware of a "next" keyword that would accomplish the same goal in one line (I asked a question about how to use it but I didn't quite understand it).

So to me, a nested for loop is much more readable. Why, then do people use "next"? I read somewhere that Python is a dynamically-typed and interpreted language and because + both concontinates strings and sums numbers, that it must check variable types for each loop iteration in order to know what the operators are, etc. Does using "next" prevent this in some way, speeding up the execution or is it just a matter of style/preference?

like image 946
aquateenfan Avatar asked Sep 06 '10 01:09

aquateenfan


1 Answers

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.

like image 92
Alex Martelli Avatar answered Oct 27 '22 16:10

Alex Martelli