comprehensions was Re: Switch statements again

Beni Cherniavsky cben at techunix.technion.ac.il
Sun Jan 19 09:12:03 EST 2003


On 2003-01-17, Tim Peters wrote:

> [Ville Vainio]
> > Of course, there is still the embarrassing issue of the list
> > comprehension variable not being local to the list comprehension. Why,
> > oh why won't people pre-deprecate it... at least in the documentation.
> > Any hope to get it into the tutorial/lang reference for 2.3 :)?
>
> [Erik Max Francis]
> > Probably for the same reason that other iterative constructs that
> > introduce variables don't make them local to that structure either:
> >
> > >>> [x for x in range(10)]
> > [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
> > >>> x
> > 9
> > >>> for y in range(10): print y,
> > ...
> > 0 1 2 3 4 5 6 7 8 9
> > >>> y
> > 9
>
> That's right, and is really all there is to it.Guido wanted
>
>   [f(x) for x in whatever]
>
> to act "exactly like"
>
>   result = []
>   for x in whatever:
>       result.append(f(x))
>
> At the time, lexical nesting didn't yet exist in Python either.The case
> for "magically local" bindings has gotten stronger since lexical nesting was
> added, but now we've got a backwards compatibility burden too.
>
There is one central use for leaving the binding alive in for loops: when
you can exit it prematurely and want to record where you did.  This is one
thing missing from list comprehensions - a way to break in the middle.
Perhaps one day a syntax for that will be added.  Especially needed when
iterating over infinite interators (generator comprehensions could
actually be better here).  If yes, then magically local bindings are a bad
idea.  The irony is that I can't seem to think of any better syntax than
``[f(x) for x in whatever while x > 0]`` which breaks the exact
equivallence with statements (the ``while x > 0`` clause should is
equivallent to ``if not x > 0: break``) :-(.

> Note that the C-ish
>
>   if ((y = f(x) != whatever)
>       do something with y
>
> can be simulated now via
>
>   if [y for y in [f(x)]][0] != whatever:
>       do something with y
>
> as is.  I hope to God nobody is doing that in real life,

Ouch.  The assignment looks dirty.  But I do use the ``for y in [f(x)]``
thing all the time because frequently my comprehensions are more readable
when I introduce intermediate bindings.  I really miss CL's ``for y =
expr`` syntax in loop (see http://www.ai.sri.com/~pkarp/loop.html and
http://www.supelec.fr/docs/cltl/clm/node247.html#SECTION003090000000000000000).

And here is a new use for the assignment clause:

>>> [sum for sum in [0]
...      for x in range(10)
...      for sum in [sum + x]]
[0, 1, 3, 6, 10, 15, 21, 28, 36, 45]

I have reached obfuscation^H^H^H^Henlightenment!  Finally, I know write
reduce comprehensions (add ``[-1]`` at the end)!  But wait, don't listen
to me, I don't want comprehensions to have as many clasuses as CL's loop
(that's more than all Python statements together :-)...

??? [sum for sum = 0
         for x in range(10)
         for sum = sum + x]  # sum += x ?

Oh, I can do without a break construct in comprehensions, except that I
lose speed:

>>> [x for flag in [1]
...    for x in range(10)
...    if flag
...       for flag in [x < 7]]
[0, 1, 2, 3, 4, 5, 6, 7]

Pretty cryptic.  (In this case the ``if flag`` is redudant but in more
general cases if would make sure no more values are produced.

Seriously, though, my biggest wish in this field are generator
comprehensions.

> but then I never expected anyone to do
>
>   (f() and [g()] or [h()])[0]
>
> in real life either <0.5 wink>.
>
That should be written ``f() and g() else h()`` <wink>.

lets-add-x,y-for-x-in-possible-syntaxes-for-y-in-possible-uses ly y'rs,
    Beni Cherniavsky <cben at tx.technion.ac.il>





More information about the Python-list mailing list