lambda in list comprehension acting funny

Daniel Fetchinson fetchinson at googlemail.com
Wed Jul 11 22:54:32 EDT 2012


>> You should not be using lambda in this case
>> .for x in [2, 3]:
>> .    funcs = [x**ctr for ctr in range( 5 )]
>> .    for p in range(5):
>> .        print x, funcs[p]
>> .    print
>
> If you change the requirements, it's always easy to solve problems. But
> it is the wrong problem that you have solved.
>
> The problem we have been asked to solve is to create a sequence of
> function objects, so that they can be called later, when needed, *not* to
> pre-calculate the results.
>
> In this case, the most obvious solution is to store a local variable in
> each function object with the value you want.
>
> funcs = [(lambda x, i=i: x**i) for i in range(5)]
>
> creates a list of five functions:
>
>     lambda x, i=0: x**i
>     lambda x, i=1: x**i
>     lambda x, i=2: x**i
>     and so on.
>
> In this case, each function has two local variables, x and i, with i
> having a default value. The function parameter i is bound to the value of
> i when the function was created.
>
> Because parameter defaults are calculated once, when the function is
> created, this causes the value of i to stick to the newly created
> function, and we get the result we need.
>
> What happens if you don't use a parameter with a default value?
>
> funcs = [(lambda x: x**i) for i in range(5)]
>
> In this case, each function body contains one local variable, x, and one
> non-local or global variable, i.
>
> Because i is a non-local, the function doesn't store a value for it.
> Instead, the function stores a lump of data pointing to just enough of
> the environment to fetch the current value of the non-local i when
> needed. Since all five functions are in the same environment, they all
> see the same value of i when you call them, regardless of what the value
> of i was when they were created.
>
> This is little different from doing this:
>
> i = 1
> def f1(x): return x**i
>
> i = 2
> def f2(x): return x**i
>
> i = 3
> def f3(x): return x**i
>
> Is there any surprise that all three functions return the same value?
> They all point to the same global variable i. I'm not sure what it is
> about lambda that fools people into thinking that it is different (I've
> even been fooled myself!) but it is not.

Thank you Steve!
Precise and clear, as always!

Cheers,
Daniel

-- 
Psss, psss, put it down! - http://www.cafepress.com/putitdown



More information about the Python-list mailing list