Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dictionary comprehension with lambda functions gives wrong results

Tags:

I tried the following code in Python 3.5.1:

>>> f = {x: (lambda y: x) for x in range(10)} >>> f[5](3) 9 

It's obvious that this should return 5. I don't understand where the other value comes from, and I wasn't able to find anything.

It seems like it's something related to reference - it always returns the answer of f[9], which is the last function assigned.

What's the error here, and how should this be done so that it works properly?

like image 224
michbad Avatar asked Apr 23 '16 00:04

michbad


People also ask

Can we use lambda in list comprehension?

List comprehension is used to create a list. Lambda function process is the same as other functions and returns the value of the list. List comprehension is more human-readable than the lambda function. User can easily understand where the list comprehension is used .

Is lambda faster than list comprehension?

Actually, list comprehension is much clearer and faster than filter+lambda, but you can use whichever you find easier. The first thing is the function call overhead: as soon as you use a Python function (whether created by def or lambda) it is likely that the filter will be slower than the list comprehension.

What are the limitations of lambda function in Python?

Cons on lambda functions:Lambda functions can have only one expression. Lambda functions cannot have a docstring. Many times lambda functions make code difficult to read. For example, see the blocks of code given below.

What is the difference between lambda and list comprehension?

The difference between Lambda and List Comprehension. List Comprehension is used to create lists, Lambda is function that can process like other functions and thus return values or lists.


1 Answers

Python scoping is lexical. A closure will refer to the name and scope of the variable, not the actual object/value of the variable.

What happens is that each lambda is capturing the variable x not the value of x.

At the end of the loop the variable x is bound to 9, therefore every lambda will refer to this x whose value is 9.

Why @ChrisP's answer works:

make_func forces the value of x to be evaluated (as it is passed into a function). Thus, the lambda is made with value of x currently and we avoid the above scoping issue.

def make_func(x):     return lambda y: x  f = {x: make_func(x) for x in range(10)} 
like image 167
gnicholas Avatar answered Sep 27 '22 20:09

gnicholas