Python: Why does 2D list comprehension require the outer loop before the inner loop?

nested list comprehension
list comprehension python
python double list comprehension with if
nested list python
python list comprehension two lists
python list comprehension multiple variables
nested if else in list comprehension python
python list comprehension multiple conditions
table = [[1, 11, 111], [2, 22, 222], [3, 33, 333]]
[cell for cell in row for row in table] # Error
[cell for row in table for cell in row] # [1, 11, 111, 2, 22, 222, 3, 33, 333]

Intuitively, the first list comprehension makes more sense. It's moving from specific to less specific, i.e. cell -> row -> table. (I find this really weird about Python list comprehensions, it should be table -> row -> cell, but I digress.)

What's the logic behind cell -> table -> row? How does the parser see this?

The for loops are meant to be the same as if you wrote them out the "normal" way:

for row in table:
    for cell in row:
        print(cell)

So when you pull this into a list comprehension, you leave the loops as is (except for removing the ":") and just pull the final expression to the start:

# you can actually "abuse" list comprehensions to have short
# loops like this, even if you don't care about the list being
# generated. It's generally not a great practice though
[print(cell) for row in table for cell in row]

I admit it is a bit confusing when you just read the code left to right. You just have to remember to read the loops first, then the beginning statement goes at the end. I suppose it could have been implemented as

[for row in table for cell in row cell]

but I think that looks even more confusing; it's harder to tell where the second loop ends and the statement within it starts. In the end, it's a design decision, though I'm sure some people would find the one approach or the other more intuitive.

Nested List Comprehensions in Python, Nested List Comprehensions are nothing but a list comprehension within another list comprehension which is quite similar to nested for loops. that execute this expression and append its output to the list until variable i iterates from 0 to 4. In this case, we need to loop over each element in the given 2-D list and append it List Comprehensions are one of the most amazing features of Python. It is a smart and concise way of creating lists by iterating over an iterable object. Nested List Comprehensions are nothing but a list comprehension within another list comprehension which is quite similar to nested for loops.

I agree that your first attempt is overall more intuitive, as it more closely mimics how I and probably most people think about iterating over things from more specific to less specific.

The nested python list comprehension is adapted from a nested for loop:

for row in table:
    for cell in row:
        cell

Concatenate the lines:

for row in table: for cell in row: cell

Wrap it in list brackets, delete :, and move the repeating expression to the front:

[cell for row in table for cell in row]

Understanding nested list comprehension syntax in Python — /var/, List comprehensions are one of the really nice and powerful features To write that, somebody would think: For a simple list comprehension I need to write [ x for x in Using the same for-loop syntax for the nested list comprehensions Until that moment I was researching the syntax every time and used� It would be good to briefly touch-base upon Nested Loops in general, before proceeding with Python specifically. If a loop exists inside the body of another loop, it is termed as Nested Loop. This means that we want to execute the inner loop code multiple times. The outer loop controls how many iterations the inner loop will undergo.

How does the parser see this?

The syntax rules for such expressions in python are called "displays". You can find the definition here.

comprehension ::=  expression comp_for
comp_for      ::=  ["async"] "for" target_list "in" or_test [comp_iter]
comp_iter     ::=  comp_for | comp_if
comp_if       ::=  "if" expression_nocond [comp_iter]

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.

The iterable expression in the leftmost for clause is evaluated directly in the enclosing scope and then passed as an argument to the implictly nested scope. Subsequent for clauses and any filter condition in the leftmost for clause cannot be evaluated in the enclosing scope as they may depend on the values obtained from the leftmost iterable.

Taking your example:

[cell for row in table for cell in row]

The interpreter will break it down like this:

expression = "cell"
comp_for1  = "for row in table" + comp_for2
comp_for2  = "for cell in row"

Then the interpreter will reconstruct the nested loop in heirachy

comp_for1:
    comp_for2:
        expression

All About Python List Comprehension | by Baijayanta Roy, Any list comprehension we can represent as a for loop, but when we represent it conditions and filter out the elements we don't need from the input list for output . This filtering happens before the output expression takes place. makes 2D flatten from a 3D list, and then the outer part does flattening to 1D. The inner for-loop must complete before the outer for-loop advances. Output c; The inner for-loop controls the second digit (j). Notice that the inner for-loop is over the list [0, 1]. Output d; The outer for-loop runs 3 times (0, 1, 2) and the inner for-loop runs twice for each time the outer for-loop runs, so this code prints exactly 6 lines.

You would think that the comprehension is inside-out version of the for loop. At least I did at first. But the easiest way for me to make sense of it is to notice that you'd call a variable before it is defined in your first attempt. row is called before it is defined. So logically you'd get an error.

[cell for cell in row ...]

row is undefined

[cell for row in table for cell in row]

No issues here

(Tutorial) Python List Comprehension, You can easily use a lambda function or a for a loop; As you well know, there Lastly, you'll dive into nested list comprehensions to iterate multiple times over lists. These values don't need to be of the same type: they can be a that starts with the variable numbers , defined as a range from 0 up until 9. Introduction and the Anatomy of a For Loop. So we'll start off with some basics so everyone is on the same page. The basic anatomy of a for loop is a little something like: for x in y: do_stuff(x,y) do_stuff(x,y) is a function call. If you don't know how functions work yet, it'll be worth looking that up before continuing here; y is an iterable

2D Lists, Create a variable-sized 2d list rows = 3 cols = 2 a = [] for row in range(rows): a += rows = 3 cols = 2 #This is what's called a "list comprehension" a = [ ([0] * cols) for row in range(rows) ] print("This IS ok. len(str(a[row][col]))) return maxLen # Because Python prints 2d lists on one row, # we Nested Looping over 2d Lists. This generic solution that also works when the nested for loop is followed by other statements. E.g. when looping over a list of sentences and using several for loops to filter out specific sentences based on existence of specific words or numbers, before doing the actual work at the end of the outer for loop. – Anthon Oct 4 '12 at 6:51

2D List Comprehension to For loop, I'm trying to convert the following list comprehension to a normal for loop, mainly The external loop stores the lists in the external list Nested List Comprehensions in Python, Nested List Comprehensions are nothing but a list case, we need to loop over each element in the given 2-D list and append it to another list. Python Loop Control Statements. Loops iterate above a block of code pending expression in testis false, but when there is an instance where we need to stop the loop without a check to the condition that is were the loop control statements come into play. The three major loop control statements in python are as below:

If you have slow loops in Python, you can fix it…until you can't, If you have slow loops in Python, you can fix it…until you can't You decide to consider all stocks from the NASDAQ 100 list as candidates for buying. We need to evaluate these two options to determine which one gives us more Inside the outer loop, initialization of grid[item+1] is 4.5 times faster for a� The outer loop executes 2 iterations (for each sub-list) and at each iteration we execute our inner loop, printing all elements of the respective sub-lists. This tells us that the control travels from the outermost loop, traverses the inner loop and then back again to the outer for loop, continuing until the control has covered the entire range

Comments
  • If you take that cell away and read it from left to right, I think it is clear enough. I believe you treat it as [(cell for cell in row) for row in table] (() only represents execution order), but actually it works as [cell ((for cell in row) for row in table)].
  • This explanation sort of helps but then cell is also called before it is defined.
  • Yes that's the only thing thing that you'd have to realize. Otherwise, it would be exactly the same as a for loop--other than the list creation.