Explanation of this Python language feature? [x for x in x for x in x] (to flatten a nested list)

Ian Kelly ian.g.kelly at gmail.com
Fri Mar 21 17:30:10 EDT 2014


On Fri, Mar 21, 2014 at 3:09 PM, Rustom Mody <rustompmody at gmail.com> wrote:
> A 'for' introduces a scope:

This is false.

>>>> x = 42
>>>> for x in [1,2,3]:
> ...   print x
> ...
> 1
> 2
> 3
>
> No sign of the 42 --v ie the outer x -- inside because of scope

Try printing x again *after* the for loop:

>>> x = 42
>>> for x in [1,2,3]:
...     print(x)
...
1
2
3
>>> print(x)
3

Notice that it's still 3.  If the x in the for loop were really a
separately scoped variable, we would have expected to see 42 here.  In
fact the x used in the for loop and the x used outside of it are the
same x variable.

The real reason that the OP's example works is because each value that
the x variable holds happens to only need to be read once.  Start with
this code, and work through it line-by-line:

x = [[1, 2], [3, 4]]
for x in x:
    for x in x:
        print(x)

Initially, x is assigned the list.  Then we enter the outer for loop.
The expression x is evaluated once to be iterated over.  The first
value that the for loop iterator yields is [1, 2], which is then
assigned to x.  Now we enter the inner for loop.  The expression x is
again evaluated once to be iterated over.  It first yields 1, which is
assigned to x, and then printed.  The inner for loop iterator then
yields 2, which is also assigned to x and printed.  The inner for loop
iterator then raises StopIteration, and the inner for loop terminates.
 The outer for loop iterator then yields [3, 4], and this is assigned
to x.  The inner for loop evaluates this expression and runs as
before.  Afterward, the outer for loop iterator raises StopException,
and that for loop terminates.  The final value of x here will be 4:

>>> x = [[1, 2], [3, 4]]
>>> for x in x:
...     for x in x:
...         print(x)
...
1
2
3
4
>>> print(x)
4

As I hope this makes clear, no nested scopes are needed to make this
happen.  It works because nothing that is stored in x needs to remain
there after the next thing is stored in x.



More information about the Python-list mailing list