1

Possible Duplicate:
What do (lambda) function closures capture in Python?

With this code :

def problem():
    PHI_LIST_0 = [lambda a, b: a+b+u for u in xrange(3)]
    PHI_LIST_1 = [lambda a, b: a+b+0, lambda a, b: a+b+1, lambda a, b: a+b+2]

    for phi in PHI_LIST_0: print "v0:", phi(1,1)
    print
    for phi in PHI_LIST_1: print "v1:", phi(1,1)

if __name__ == '__main__':
    problem()

I get:

v0: 4
v0: 4
v0: 4

v1: 2
v1: 3
v1: 4

The expected behavior is the last one, with PHI_LIST_1. I think I understand why the results differ with PHI_LIST_0: maybe because Python uses the last 'u', ie 2, when phi(1,1) is evaluated.

But I would like to declare a list of functions the way PHI_LIST_0 is defined, with a list comprehension. Does anybody know how I could do that ?

Community
  • 1
  • 1

1 Answers1

2

When you define a function, it creates a closure over the free variables in the body of the function. In your PHI_LIST_0, that's the variable u. It doesn't keep the value of u, it keeps a reference to the name u. When you invoke the function, it uses the current value of u. So all of your functions refer to the same variable, and all see the same (last) value of it, so they all behave the same.

You can solve this with the default-value trick:

PHI_LIST_0 = [lambda a, b, u=u: a+b+u for u in xrange(3)]

Now the default value of the u parameter is computed when the function is defined, and is stored with the function.

Ned Batchelder
  • 364,293
  • 75
  • 561
  • 662
  • that is what i thought, but then i use `copy` to get the value of `u` and it still did not work as expected. - but your solution is elegant and it works nicely. :) – Inbar Rose Dec 11 '12 at 15:46