RELEASED Python 2.4, alpha 1

Bengt Richter bokr at oz.net
Sat Jul 10 16:18:38 EDT 2004


On 9 Jul 2004 11:38:00 -0700, michele.simionato at gmail.com (Michele Simionato) wrote:

>Anthony Baxter <anthony at python.org> wrote in message news:<mailman.157.1089357112.5135.python-list at python.org>...
>> On behalf of the Python development team and the Python community, I'm
>> happy to announce the first alpha of Python 2.4.
>> <snip>
>
>Uhm ... I see generator expressions have late bindings, just as list comprehensions:
>
>>>> f1,f2,f3=tuple(lambda : i for i in [1,2,3])
>>>> f1()
>3
>>>> f2()
>3
>>>> f3()
>3
>
I guess I don't know what you mean by "late binding" -- i.e., I don't see
a semantic difference between (I don't have the generator expression version yet):

 >>> f1,f2,f3=[lambda : i for i in [1,2,3]]
 >>> f1(),f2(),f3()
 (3, 3, 3)

and

 >>> lamb = lambda : i
 >>> f1,f2,f3=[lamb for i in [1,2,3]]
 >>> f1(),f2(),f3()
 (3, 3, 3)

ISTM it is a matter of late lookup, more than late binding. I.e.,
the lambda expression specifies lookup of a name "i" when it is executed:

 >>> import dis
 >>> dis.dis(lambda : i)
   1           0 LOAD_GLOBAL              0 (i)
               3 RETURN_VALUE

The list comprehension didn't generate a different lookup:
 >>> f1,f2,f3=[lambda : i for i in [1,2,3]]
 >>> dis.dis(f1)
   1           0 LOAD_GLOBAL              0 (i)
               3 RETURN_VALUE

BTW, if list comprehension variables bound in a loop-private scope instead of
the enclosing scope, the lookup of i would fail unless otherwise set ;-)
Will generator expressions bind in the eclosing scope too? Have the consequences been discussed?

Anyway, as I think you know, to get your desired end result, you have to create lambdas
that will do their lookups referring to different i's -- which you can do with closures, e.g.,

 >>> f1,f2,f3=[(lambda i: lambda : i)(i) for i in [1,2,3]]
 >>> f1(),f2(),f3()
 (1, 2, 3)
 >>> dis.dis(f1)
   1           0 LOAD_DEREF               0 (i)
               3 RETURN_VALUE

Or here's another of several other possible ways:

 >>> f1,f2,f3=[(lambda i:i).__get__(i,int) for i in [1,2,3]]
 >>> f1(),f2(),f3()
 (1, 2, 3)
 >>> dis.dis(f1)
   1           0 LOAD_FAST                0 (i)
               3 RETURN_VALUE

BTW, those are bound methods ...
 >>> f1,f2,f3
 (<bound method int.<lambda> of 1>, <bound method int.<lambda> of 2>, <bound method int.<lambda> of 3>)


>I was more in the camp of early bindings; I would like to know if late
>bindings are final or subject to changes and it there a pronouncement
>from Guido.
>
>
>               Michele Simionato

Regards,
Bengt Richter



More information about the Python-list mailing list