A good translation for i in <whatever>: <loopbody> showing what exactly it does for any <whatever> and any <loopbody> :
_aux = iter(<whatever>) while True: try: i = next(_aux) except StopIteration: break <loopbody>
except that the pseudo-variable that I call _aux here actually remains unnamed.
So, <whatever> always evaluated only once (to get iter() from it), and the resulting iterator will be next ed until it ends (if the <loopbody> ) has no break ).
Using listcomp, as you used, evaluation creates a list object (which in your code example remains unnamed). In a very similar code:
for item in (i * 2 for i in range(1, 10)): ...
using the xp gene rather than listcomp (syntax, parentheses instead of listcomp square brackets), it is next() , which actually does most of the work ( i progresses and doubles it) instead of dumping all the work at build time - it takes less temporary memory and can save time if the body of the loop can reasonably break exit earlier, but, with the exception of such special conditions (very tight memory or probable early termination of the loop), a listcomp can usually be (a little bit).
source share