classification
Title: list comprehension for flattened or nested list differ too much
Type: enhancement Stage: resolved
Components: Versions:
process
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: Nosy List: Yechoh, steven.daprano
Priority: normal Keywords:

Created on 2018-11-14 13:24 by Yechoh, last changed 2018-11-14 14:21 by steven.daprano. This issue is now closed.

Messages (2)
msg329906 - (view) Author: (Yechoh) Date: 2018-11-14 13:24
Suppose we have:
forest = [[1,2],[3,4]]
and we want:
l1 = [['1','2'],['3','4']]
we could write:
l1 = [[str(leaf) for leaf in tree] for tree in forest]

Now if we want:
l2 = ['1','2','3','4']
What I expect to need to write is:
l2 = [str(leaf) for leaf in tree for tree in forest]
However, this gives an error:
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'tree' is not defined
Instead, I should write:
l2 = [str(leaf) for tree in forest for leaf in tree]
Notice the different order.
I would prefer if the first version of constructing l2 over the second, since it follows closer to the reading order.
Also, it is closer to the comprehension for a nested list, so changing a nested list comprehension to a flattened list comprehension is easy.
msg329910 - (view) Author: Steven D'Aprano (steven.daprano) * (Python committer) Date: 2018-11-14 14:21
> l2 = [str(leaf) for leaf in tree for tree in forest]

Expanded to nested loops, that becomes:

l2 = []
for leaf in tree:
    for tree in forest:
        l2.append(str(leaf))

which of course gives a NameError, because you are trying to iterate over a tree that you haven't defined yet.

The correct way to write this nested comprehension is to put the loops in the same order that they will appear in a nested loop:

[str(leaf) for tree in forest for leaf in tree]

There are thousands, or more, of nested comprehensions using the existing order in code around the world, if we swapped to your proposed "backwards" order it would change the meaning of their code and break it. That's not going to happen without an excellent reason.

I'm closing this "rejected". If you want to debate this and push for the proposed change, you should discuss it on the Python-Ideas mailing list first.
History
Date User Action Args
2018-11-14 14:21:58steven.dapranosetstatus: open -> closed

nosy: + steven.daprano
messages: + msg329910

resolution: rejected
stage: resolved
2018-11-14 13:24:33Yechohcreate