On Sep 28, 1:14 am, Marc 'BlackJack' Rintsch <[EMAIL PROTECTED]> wrote: > On Sat, 27 Sep 2008 21:43:15 -0700, Aaron \"Castironpi\" Brady wrote: > > 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 > > `n` is looked up at the time ``f[0]`` is called. At that time it is > bound to 9. > > >>>> 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? > > It *does* look up `n` at the time you call ``f[0]`` but this time it's > the local `n` of the outer ``lambda`` function and that is bound to > whatever the function was called with. At the time it was called the > global `n` was bound to 0. Maybe it get's more clear if you don't name > it `n`: > > In [167]: f = [None] * 10 > > In [168]: for n in xrange(10): > .....: f[n] = (lambda x: lambda: x)(n) > .....: > > In [169]: f[0]() > Out[169]: 0 > > Ciao, > Marc 'BlackJack' Rintsch
Hi Marc, It's my understanding that 'n' gets a new value every time through the loop. n= 0 on the first pass, n= 1 on the second pass, and so on. n= 9 by the end, and that's why `lambda: n` always returns 9. It queries the variable 'n', and finds 9. (This got lengthy. I started thinking aloud.) In your version of the indirect example, it queries the variable 'x', which it finds in a new distinct scope in each f element. In f[0], x= 0. In f[1], x= 1. There are 10 different 'x' variables throughout the contents of f. The direct example does not do this allocation of ten different 'x's. It's sort of helping. I think I feel like the following is more like what I'm looking for: (Non-standard) >>> f= [ None ]* 10 >>> for n in range( 10 ): ... f[ n ]= n ... >>> f[0] 9 >>> f[1] 9 because when you access f[0], it looks up the variable 'n'. Obviously not. (Unproduced) >>> f= [ None ]* 10 >>> for n in range( 10 ): ... f[ n ]= late( n ) #late/lazy ... >>> f[0] 9 >>> f[1] 9 >>> f= [ None ]* 10 >>> for n in range( 10 ): ... f[ n ]= early( n ) #early/eager ... >>> f[0] 0 >>> f[1] 1 For the functions, I want a function that returns 'n', either late or early. (Unproduced) >>> for n in range( 10 ): ... f[ n ]= lambda: late( n ) >>> f[0]() 9 >>> for n in range( 10 ): ... f[ n ]= lambda: early( n ) >>> f[0]() 0 I don't think you could pull this off. 'late' and 'early' succeed with quotes around n, early('n') and late('n'), in the direct assignments, but the functions aren't so lucky. 'n' has gone on to a better world by the time 'early' gets any control. This might have some success. (Unproduced) >>> for n in range( 10 ): ... f[ n ]= late( lambda: n ) >>> f[0]() 9 >>> for n in range( 10 ): ... f[ n ]= early( lambda: n ) >>> f[0]() 0 Though it's beyond my foresight to tell if it's feasible as stated, if you need quotes, how much introspection you would need, etc. Plus, 'late' and 'early' were accepting quoted parameters earlier. How would they look inside a function? Could a simple decorator provide the service? On a tangent about mutables, it's not that numbers, strings, and tuples are 'immutable' per se, it's just that they don't have any methods which mutate them (or assignable properties). Lists and dictionaries do. It's up to the user whether a custom class does. -- http://mail.python.org/mailman/listinfo/python-list