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