Autogenerate functions (array of lambdas)

David Stanek dstanek at dstanek.com
Thu Sep 6 11:00:12 CEST 2007

```On 9/6/07, Chris Johnson <effigies at gmail.com> 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20070906/a7b116ce/attachment.html>
```