4
def multipliers():
  l = []
  for i in range(4):
    l.append(lambda x : x * i )
  return l

>>> ll[0](2)
6
>>> ll[1](2)
6
>>> ll[2](2)
6
>>> ll[3](2)
6

Can you explain the result here? I was hoping to get:

0
2
4
6
Ankur Agarwal
  • 23,692
  • 41
  • 137
  • 208
  • 1
    related: http://stackoverflow.com/questions/2295290/what-do-lambda-function-closures-capture-in-python (see the second answer for how to deal with your problem, and the first to explain why it happens) – NightShadeQueen Jul 27 '15 at 22:46
  • Although I don't blame you for not finding that: it took me like four tries with Google, despite the fact I knew that question existed. – NightShadeQueen Jul 27 '15 at 22:48
  • `site:stackoverflow.com python lambda` turns up several good results (including that one). – TigerhawkT3 Jul 27 '15 at 22:49
  • 1
    As pointed out in the thread, a simple way to solve this issue is to use `i` as a default argument for the lambda: `lambda x, i=i: x*i` – Vincent Jul 27 '15 at 22:56

3 Answers3

3

The reason for this is that Python’s closures are late binding. This means that the values of variables used in closures are looked up at the time the inner function is called. So as a result, when any of the functions returned by multipliers() are called, the value of i is looked up in the surrounding scope at that time. By then, regardless of which of the returned functions is called, the for loop has completed and i is left with its final value of 3. Therefore, every returned function multiplies the value it is passed by 3, so since a value of 2 is passed in the above code, they all return a value of 6

Taken from : http://www.toptal.com/python/interview-questions

letsc
  • 2,515
  • 5
  • 35
  • 54
3

The problem is that, as people say, i is not a local variable of the lambda. You have to fix that: using a default parameter value changing during the loop:

>>> def multipliers():
  l = []
  for i in range(4):
    l.append(lambda x, i=i : x * i )
  return l

>>> lst = multipliers()
>>> lst[0](2)
0
>>> lst[1](2)
2
>>> lst[2](2)
4
>>> lst[3](2)
6
>>> 
Clodion
  • 1,017
  • 6
  • 12
1

The value of i is not stored inside the lambda function. That's why you're getting the result you're seeing: Python is using the value of i it finds when the function is called.

Simeon Visser
  • 118,920
  • 18
  • 185
  • 180