closures and dynamic binding

Terry Reedy tjreedy at udel.edu
Sun Sep 28 03:46:57 EDT 2008


Aaron "Castironpi" Brady wrote:
> Hello all,
> 
> To me, this is a somewhat unintuitive behavior.  I want to discuss the
> parts of it I don't understand.
> 
>>>> f= [ None ]* 10
>>>> for n in range( 10 ):
> ...     f[ n ]= lambda: n

This is equivalent to

for n in range(10):
   def g(): return n
   f[n] = g

which is equivalent to

def g(): return n
f = [g]*10
n = 9

>>>> f[0]()
> 9
>>>> f[1]()
> 9

which make this not so surprising as the original lambda version is to 
some people.

> I guess I can accept this part so far, though it took a little getting
> used to.  I'm writing some code and found the following workaround,
> but I don't think it should give different results.  Maybe I'm not
> understanding some of the details of closures.
> 
>>>> f= [ None ]* 10
>>>> for n in range( 10 ):
> ...     f[ n ]= (lambda n: ( lambda: n ) )( n )

This is equivalent to

for n in range(10):
   def g(n):
     def h:
       return n
     return h
   f[n] = g(n)

Now, to avoid the needless confusion of 'n's, g is equivalent to

def g(x):
   def h:
     return x
   return h

(One could do the same change in the lambdas, too, of course).
so that g(n)() == n, with n stored in each closure h...

> ...
>>>> f[0]()
> 0
>>>> f[1]()
> 1

to be regurgitated when each is called.

Terry Jan Reedy




More information about the Python-list mailing list