Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating lambda expressions on the fly [duplicate]

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
like image 307
Ankur Agarwal Avatar asked Mar 15 '23 06:03

Ankur Agarwal


2 Answers

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
>>> 
like image 126
Clodion Avatar answered Mar 17 '23 20:03

Clodion


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

like image 29
letsc Avatar answered Mar 17 '23 21:03

letsc