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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With