[Python-Dev] Iteration variables and list comprehensions

David Beazley beazley@cs.uchicago.edu
Tue, 29 May 2001 11:56:09 -0500 (CDT)


I'm not sure if this has ever been brought up before (I don't recall
seeing it), but I would like to throw out something that has been
bugging me about list comprehensions for quite some time...

First of all, I have to say that I've really grown to like list
comprehensions a lot.  In fact, I find myself using them in just about
every Python program I've been writing since switching to Python 2.0.
However, I've also been shooting myself in the foot a little more than
usual due to the following issue:

When I write a list comprehension like this:

    s = [ expr(x) for x in t ]

it is *VERY* easy to overlook the fact that the iteration variable "x"
is evaluated in the local scope (and replaces any previous binding
to "x" that might have existed outside the context of the list
comprehension).    Because of this, I have frequently found myself
debugging the following programming error:

   # Some loop
   for x in r:
       ...
       # bunch of statements
       ...
       s = [expr(x) for x in t]
       ...
       # Try to do something with x.
       # ???? What in the hell is wrong with my program ????
       ...

The main problem is that I conceptually tend to think of the list
comprehension as being some kind of list operator where the index name
is really one of the operands in some sense.  Because of this, it is
*VERY* easy to get in the habit of throwing list comprehensions all
over the place, each of which uses a common index name like x,i,j,
etc.  Of course, this works just fine until you forget that you're
also using x,i,j for some kind of loop variable someplace else :-).

Therefore, I'm wondering if it would make any sense to make the
iterator variables used inside of a list comprehension private in some
manner--either through name mangling or some other technique? For
example:

   s = [expr(x) for x in t]

would get expanded into something roughly like this:

   s = [ ]
   for _mangled_x in t:
       s.append(expr(_mangled_x))
   del _mangled_x

Just as an aside, I have never intentionally used the iterator
variable of a list comprehension after the operation has completed. I
was actually quite surprised with this behavior the first time I saw
it.  I suspect most other programmers would not anticipate this side
effect either.

Comments?

Cheers,

Dave