Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lambda in a loop [duplicate]

Considering the following code snippet:

# directorys == {'login': <object at ...>, 'home': <object at ...>} for d in directorys:     self.command["cd " + d] = (lambda : self.root.change_directory(d)) 

I expect to create a dictionary of two function as following :

# Expected : self.command == {     "cd login": lambda: self.root.change_directory("login"),     "cd home": lambda: self.root.change_directory("home") } 

but it looks like the two lambda function generated are exactly the same :

# Result : self.command == {     "cd login": lambda: self.root.change_directory("login"),     "cd home": lambda: self.root.change_directory("login")   # <- Why login ? } 

I really don't understand why. Do you have any suggestions ?

like image 356
FunkySayu Avatar asked Nov 07 '13 13:11

FunkySayu


People also ask

Can I use for loop in lambda?

Since a for loop is a statement (as is print , in Python 2. x), you cannot include it in a lambda expression.

Can lambda return 2 values?

That's not more than one return, it's not even a single return with multiple values. It's one return with one value (which happens to be a tuple).

Can a lambda have multiple expression?

Lambda functions can only have one expression in their body. Regular functions can have multiple expressions and statements in their body.

Can Python lambda have multiple statements?

Lambda functions does not allow multiple statements, however, we can create two lambda functions and then call the other lambda function as a parameter to the first function.


1 Answers

You need to bind d for each function created. One way to do that is to pass it as a parameter with a default value:

lambda d=d: self.root.change_directory(d) 

Now the d inside the function uses the parameter, even though it has the same name, and the default value for that is evaluated when the function is created. To help you see this:

lambda bound_d=d: self.root.change_directory(bound_d) 

Remember how default values work, such as for mutable objects like lists and dicts, because you are binding an object.

This idiom of parameters with default values is common enough, but may fail if you introspect function parameters and determine what to do based on their presence. You can avoid the parameter with another closure:

(lambda d=d: lambda: self.root.change_directory(d))() # or (lambda d: lambda: self.root.change_directory(d))(d) 
like image 56
Roger Pate Avatar answered Sep 18 '22 05:09

Roger Pate