A good translation of for i in <whatever>: <loopbody>
, showing exactly what 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 I have here named _aux
actually remains unnamed.
So, <whatever>
always gets evaluated just once (to get an iter()
from it) and the resulting iterator is next
ed until it runs out (unless there's some break
in the <loopbody>
).
With a listcomp, as you've used, the evaluation produces a list
object (which in your code sample remains unnamed). In the very similar code:
for item in (i * 2 for i in range(1, 10)): ...
using a genexp rather than the listcomp (syntactically, round parentheses instead of the listcomp's square brackets), it's the next()
that actually does most of the work (advancing i
and doubling it), instead of lumping all work at construction time -- this takes up less temporary memory, and may save time if the loop body's reasonably likely to break
out early, but except in such special conditions (very tight memory or likely early loop termination) a listcomp may typically be (by a wee little bit) faster.