8

I am trying to generate several functions with different parameter i (see below) using a for loop, but it seems that all these functions are using the last item of i's. Could anyone tell me how to handle this?

This is a simplified example. I actually need to generate more than 200 functions with different parameters.

funs = ()
for i in range(2):
    f = lambda x: x+i
    funs += (f,)

Then it turns out that the two functions do the same thing:

funs[0](1)

Output: 2

funs[1](1)

Output: 2

But I expect the first function to give a result of 1 rather than 2.

Thank you very much in advance.

Ivy.Zheng
  • 81
  • 2
  • If you can generate the functions you can do it with one. Python functions are very dynamic. – Klaus D. Jul 12 '17 at 15:37
  • 6
    See [Why do lambdas defined in a loop with different values all return the same result?](https://docs.python.org/3/faq/programming.html#why-do-lambdas-defined-in-a-loop-with-different-values-all-return-the-same-result) from the Python FAQ. – Daniel Roseman Jul 12 '17 at 15:40

2 Answers2

6

The reason you're getting the same result for all the functions is because i is not local to the lambdas, but is defined in the outer scope, and it is accessed when the lambda is called - not when it is defined. At the end of the loop, the value of i is 1 and thus, it uses 1 for every call to the lambda functions.

Jean-Francois Fabre gave one good solution but I personally prefer this:

list_ = []
for i in range(2):
    f = lambda x, n=i: x+n
    list_.append(f)
itachi
  • 103
  • 7
5

you have to break the dynamic binding to i, for instance by wrapping 2 lambdas together:

f = (lambda p : lambda x: x+p)(i)

that way, the value of i is captured, and functions hold a copy of i

Aside: I wouldn't use tuple to create the list for performance reasons when appending to funs (funs = () => funs = [])

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219