On 9/6/07, Chris Johnson <[EMAIL PROTECTED]> wrote: > > What I want to do is build an array of lambda functions, like so: > > a = [lambda: i for i in range(10)] > > (This is just a demonstrative dummy array. I don't need better ways to > achieve the above functionality.) > > print [f() for f in a] > > results in: [9, 9, 9, 9, 9, 9, 9, 9, 9, 9] > rather than the hoped for: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] > > Clearly, lambda is returning the object i, which is left at the last > value of range(10). The following is my solution. > > t = lambda i: lambda: i > a = [t(i) for i in range(10)] > > or the somewhat more terse: > > a = [(lambda i: lambda: i)(i) for i in range(10)] > > This gives the behavior which, intuitively, I expected from the > original syntax. So my questions are: > 1) Does this make sense as what should be done here? That is, would > this be the behavior you'd want more often than not? As I said, > intuitively, I would think the lambda would treat the iterator > variable as a constant in this context. > 2) Is there a better or preferred method than the one I've found?
A more explicit example of your solution would be: >>> def gen(i): ... return lambda: i # bind to the i passed in ... >>> l = [gen(i) for i in range(10)] >>> [f() for f in l] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] Your initial lambda: i creates a function that binds to i in the current scope. When you wrapped that in another lambda you were creating a new scope with a new value of i and returning a function bound to that value for i. Take a look at closures: http://www.ibm.com/developerworks/linux/library/l-prog2.html#h1 http://ivan.truemesh.com/archives/000392.html David -- http://www.traceback.org
-- http://mail.python.org/mailman/listinfo/python-list