On Sep 28, 2:52 am, Steven D'Aprano <[EMAIL PROTECTED] cybersource.com.au> wrote: > On Sat, 27 Sep 2008 21:43:15 -0700, 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 > > ... > >>>> f[0]() > > 9 > >>>> f[1]() > > 9 > > > 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 ) > > ... > >>>> f[0]() > > 0 > >>>> f[1]() > > 1 > > > Which is of course the desired effect. Why doesn't the second one just > > look up what 'n' is when I call f[0], and return 9? > > That's an awfully complicated solution. A much easier way to get the > result you are after is to give each function its own local copy of n: > > f[n] = lambda n=n: n > > As for why the complicated version works, it may be clearer if you expand > it from a one-liner: > > # expand: f[ n ]= (lambda n: ( lambda: n ) )( n ) > > inner = lambda: n > outer = lambda n: inner > f[n] = outer(n) > > outer(0) => inner with a local scope of n=0 > outer(1) => inner with a local scope of n=1 etc. > > Then, later, when you call inner() it grabs the local scope and returns > the number you expected. > > -- > Steven
Steven, I must have misunderstood. Here's my run of your code: >>> inner = lambda: n >>> outer = lambda n: inner >>> outer(0) <function <lambda> at 0x00A01170> >>> a=outer(0) >>> b=outer(1) >>> a() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 1, in <lambda> NameError: global name 'n' is not defined Why doesn't 'inner' know it's been used in two different scopes, and look up 'n' based on the one it's in? -- http://mail.python.org/mailman/listinfo/python-list