Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is Python's list comprehension loop order backwards? [duplicate]

>>> my_list = [[[[1, 2, 3], [4, 5, 6], ]]]
>>> [a for d in my_list for c in d for b in c for a in b]
[1, 2, 3, 4, 5, 6]

is equivalent to

>>> my_list = [[[[1, 2, 3], [4, 5, 6], ]]]
>>> new_list = []
>>> for d in my_list:
...     for c in d:
...         for b in c:
...             for a in b:
...                 new_list.append(a)
... print(new_list):
[1, 2, 3, 4, 5, 6]

This syntax seems backwards when read from left-to-right. According to PEP 202, "The form [... for x... for y...] nests, with the last index varying fastest, just like nested for loops." is "the Right One."

It seems that this order (of left-to-right corresponding to outer-to-inner nested for loops) was chosen because that is the order in which nested for loops are written.

However, since the expression part of the list comprehension (a in the above example), corresponds to the expression at the inner-most part of the nested loops (new_list.append(a) in the above example), it seems to me that the for _ in _ closest to this expression should be the same in both cases, i.e. it should be for a in b and on outwards:

>>> my_list = [[[[1, 2, 3], [4, 5, 6], ]]]
>>> [a for a in b for b in c for c in d for d in my_list]
NameError: name 'b' is not defined

so that the fastest-changing loop is closest to the action, so-to-speak. This also lends itself to being read from left-to-right in more logically stepwise fashion.

Is this a common sentiment among users? or does anyone have a good counter-argument as to why the current syntax implementation really is "the Right One"?

like image 805
jameh Avatar asked Oct 21 '13 00:10

jameh


People also ask

Does Python list comprehension maintain order?

Yes, the list comprehension preserves the order of the original iterable (if there is one). If the original iterable is ordered (list, tuple, file, etc.), that's the order you'll get in the result. If your iterable is unordered (set, dict, etc.), there are no guarantees about the order of the items.

Why list comprehension is faster than for loop?

List comprehensions are faster than for loops to create lists. But, this is because we are creating a list by appending new elements to it at each iteration.


1 Answers

Consider:

[leaf for branch in tree for leaf in branch]

It unrolls like:

for branch in tree:
    for leaf in branch:
        yield leaf

If we write it the other way

[leaf for leaf in branch for branch in tree]

It might make more sense in plain English on some level, but a possible counter-argument is that here the name "branch" is used without being (yet) defined.

like image 56
wim Avatar answered Oct 02 '22 17:10

wim