Functional programming gotcha

David C. Fox davidcfox at post.harvard.edu
Fri Oct 24 15:30:52 EDT 2003


Ed Schofield wrote:

> Hi all,
> 
> I find this strange:
> 
> 
>>>>flist = []
>>>>for i in range(3):
> 
> ...     f = lambda x: x+i
> ...     flist.append(f)
> ...
> 
>>>>[f(1) for f in flist]
> 
> [3, 3, 3]
> 
> 
> What I expect is:
> 
> 
>>>>[f(1) for f in flist]
> 
> [1,2,3]
> 
> 
> Is this a bug in Python?  It happens on my builds of
> Python 2.3 and 2.2.3.

I guess the nested scopes changes in Python 2.1/2.2 (see 
http://www.python.org/peps/pep-0227.html) apply to functions but not 
loops.  You can use the same workaround that people used to use because 
of the lack of nested scopes:

f = lambda x, i = i: x + i

That way, the second, optional parameter has a default value which is 
evaluated at the time the lambda is created.

> 
> Replacing the lambda function by a named function, as in
> 
> flist = []
> for i in range(3):
>     def f(x):
>         return x + i
>     flist.append(f)
> 
> [f(1) for f in flist]
> 
> gives the same result.
> 
> I have a workaround (of sorts) adapted from the Python tutorial:
> 
> 
>>>>def make_incrementor(n):
> 
> ...     return lambda x: x + n
> ...
> 
>>>>flist = [make_incrementor(i) for i in range(3)]
>>>>
>>>>[f(1) for f in flist]
> 
> [1, 2, 3]
> 
> 
> but I'd prefer the flexibility of the first approach.  Any ideas?
> 
> Any explanations for why Python does this?  Any justifications for why
> Python _should_ do this?  Who believes this is a bug?
> 
> Kind regards,
> Ed Schofield
> 





More information about the Python-list mailing list