Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python list comprehension with lambdas [duplicate]

Tags:

I'm running Python 3.4.2, and I'm confused at the behavior of my code. I'm trying to create a list of callable polynomial functions with increasing degree:

bases = [lambda x: x**i for i in range(3)] 

But for some reason it does this:

print([b(5) for b in bases]) # [25, 25, 25] 

Why is bases seemingly a list of the last lambda expression, in the list comprehension, repeated?

like image 891
henrywallace Avatar asked Feb 01 '15 21:02

henrywallace


1 Answers

The problem, which is a classic "gotcha", is that the i referenced in the lambda functions is not looked up until the lambda function is called. At that time, the value of i is the last value it was bound to when the for-loop ended, i.e. 2.

If you bind i to a default value in the definition of the lambda functions, then each i becomes a local variable, and its default value is evaluated and bound to the function at the time the lambda is defined rather than called.

Thus, when the lambda is called, i is now looked up in the local scope, and its default value is used:

In [177]: bases = [lambda x, i=i: x**i for i in range(3)]  In [178]: print([b(5) for b in bases]) [1, 5, 25] 

For reference:

  • Python scopes and namespaces
like image 84
unutbu Avatar answered Sep 23 '22 07:09

unutbu