On Sat, Oct 24, 2009 at 8:33 PM, Michal Ostrowski <mostr...@gmail.com> wrote: > The snippet of code below uses two functions to dynamically create > functions using lambda. > Both of these uses should produce the same result, but they don't. <snip> > def MakeLambdaGood(): > def DoLambda(x): > return lambda q: x + q > a = [] > for x in [1,2]: > a.append(DoLambda(x)) > return a > > def MakeLambdaBad(): > a = [] > for x in [1,2]: > a.append(lambda q: x + q) > return a > > [a,b] = MakeLambdaBad() > print a(10) > print b(10) > [a,b] = MakeLambdaGood() > print a(10) > print b(10) <snip> > The expected output of this code is > > 11 > 12 > 11 > 12 > > However, what we get instead is > > 12 > 12 > 11 > 12 > > The problem is that the two functions returned by MakeLambdaBad() are > apparently the same, but the functions returned by MakeLambdaGood() > are different. > > Can anyone explain why this would/should be the case?
This comes up often enough there should be a FAQ entry on it. A decent explanation of the problem: http://lackingrhoticity.blogspot.com/2009/04/python-variable-binding-semantics-part.html Essentially, the lambdas in MakeLambdaBad() *don't* capture the value of x at the time they are *created*; they both just reference the same variable x in the function's scope and both use whatever its "current value" at the time they get *called*. x's value gets frozen at 2 when MakeLambdaBad() returns and the rest of the variables in x's scope are destroyed; hence, they both use 2 as x's value. The common workaround for the problem is to use the default argument values mechanism in the lambdas. MakeLambdaGood() avoids the problem by forcing x's evaluation (via DoLambda()) at the time the lambdas are created (as opposed to called) and thus reference x's value rather than x itself as a variable. Cheers, Chris -- http://blog.rebertia.com -- http://mail.python.org/mailman/listinfo/python-list