Monday, February 18, 2013

Doubly-indexed comprehensions

A nonintuitive (for me) feature of comprehensions in Python:

Python supports doubly (triply...) indexed list/generator comprehensions. Let's say we want to do something equivalent to the following:
foo = []
for iter1 in range(6):
 for iter2 in range(7):
    foo.append(bar(iter1,iter2))
but without the double loop or initialization. This can be done in just one list comprehension as follows:
foo = [bar(iter1,iter2) for iter1 in range(6) for iter2 in range(7)]
What's surprising about this to me is that, when trying to parse this, my instinct is to associate the for loops in such a way that the range(7) loop is outermost, because the whole statement (bar(iter1,iter2) for iter1 in range(6) looks to me like the body of the range(7) loop. However, the Python team decided to do it the other way: loops in a comprehension evaluate left to right outer to inner.

The reason for this, I'm sure, is so that a developer can take code written with old-style loops and refactor it into a generator expression without the added pain and suffering of reversing the order the loops are written in. A noble goal, to be sure.

No comments:

Post a Comment