lambda in list comprehension acting funny

Steven D'Aprano steve+comp.lang.python at pearwood.info
Fri Jul 13 23:43:24 EDT 2012


On Fri, 13 Jul 2012 19:31:24 -0700, rusi wrote:

> Consider the following
> 
> def foo(x):
>     i = 100
>     if x:
>         j = [i for i in range(10)]
>         return i
>     else:
>         return i

A simpler example:

def foo():
    i = 100
    j = [i for i in range(10)]
    return i

In Python 3, foo() returns 100; in Python 2, it returns 9.


> In python 2  two different 'i's could be returned. In python3 only one i
> can be returned.
> One could call it dynamic binding. 

One could also call it a tractor, but it isn't either of those things.

The difference is whether or not list comprehensions create their own 
scope. In Python 2, they don't; in Python 3, they do. Personally I don't 
have an opinion as to which is better, but in neither case does this have 
any thing to do with lexical versus dynamic binding.


> Evidently Guido thinks it a bug which is why he changed it.

It was a case that either list comps be changed to *not* expose their 
loop variable, or generator expressions be changed *to* expose their loop 
variable. The Python 2 situation where list comps and gen expressions 
have opposite behaviour was unfortunate.


> The leakage of i in the OPs question is the same kind of bug.

Not at all. The OP was *deliberately* creating a closure using i -- under 
those circumstances, it would be a bug if i *didn't* leak.

The OP's gotcha was:

1) he expected the closure to use early binding, where i in each function 
was bound to the value of i in the enclosing scope at the moment the 
function was defined; 

2) but Python actually uses late binding for closures, where the value of 
i in each function is set to the value of i in the enclosing scope when 
the function is called.

As far as I can tell, Python always uses late binding for scopes; the 
only time it does early binding is for default values of function 
parameters.



-- 
Steven



More information about the Python-list mailing list