On 29/01/2013 18:53, Terry Reedy wrote:
On 1/29/2013 10:02 AM, Rob Cliffe wrote:
On 29/01/2013 10:44, Nick Coghlan wrote:
Terry is correct: comprehensions are deliberately designed to have the exact same looping semantics as the equivalent statements flattened out into a single line, with the innermost expression lifted out of the loop body and placed in front. This then works to arbitrarily deep nesting levels. The surrounding syntax (parentheses, brackets, braces, and whether or not there is a colon present in the main expression) then governs what kind of result you get (generator-iterator, list, set, dict).
For example in:
(x, y, z for x in a if x for y in b if y for z in c if z) [x, y, z for x in a if x for y in b if y for z in c if z] {x, y, z for x in a if x for y in b if y for z in c if z} {x: y, z for x in a if x for y in b if y for z in c if z}
The looping semantics of these expressions are all completely defined by the equivalent statements:
for x in a: if x: for y in b: if y: for z in c: if z:
(modulo a few name lookup quirks if you're playing with class scopes)
Thanks for spelling this out so clearly. It helps me remember which order to place nested "for"s inside a list comprehension! :-)
The reference manual does spell it out: "In this case, the elements of the new container are those that would be produced by considering each of the for or if clauses a block, nesting from left to right, and evaluating the expression to produce an element each time the innermost block is reached." Perhaps a non-trivial concrete example (say 4 levels deep) would help people understand that better.
Definitely. +1. Though I think 3 levels is enough.