Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this lambda function act weirdly in an else statement?

Can someone explain to me why I get <function <lambda>.<locals>.<lambda> at 0x0000000002127F28> instead of 3?

>>> foo = True
>>> bar = lambda x: x + 1 if foo else lambda x: x + 2
>>> bar(1)
2

>>> foo = False
>>> bar = lambda x: x + 1 if foo else lambda x: x + 2
>>> bar(1)
<function <lambda>.<locals>.<lambda> at 0x0000000002127F28>   # Hey !? WTF ? 
like image 901
snoob dogg Avatar asked Jul 15 '18 16:07

snoob dogg


1 Answers

Python has a different order of operations than you think here. It seems you should change your definition to

bar = (lambda x: x + 1) if foo else (lambda x: x + 2)

What you were actually getting with your definition was

bar = lambda x: (x + 1 if foo else lambda x: x + 2)

In other words, you were returning a function, and if foo is true the function returns the value of x+1 but if it is false it returns the function lambda x: x + 2. What you really wanted was to return one of two functions, which the modified definition does.

The moral of this story: use plenty of parentheses to make your intentions clear.


A comment to your question suggests another possibility:

bar = lambda x: x + 1 if foo else x + 2

which is equivalent to

bar = lambda x: (x + 1 if foo else x + 2)

This is not the same as my suggestion. My suggestion, when executed, returns one of two functions. One function always adds one, the other always adds 2, and which function is returned depends on the value of foo when the definition line is executed. The alternative here returns just one function, and this function adds one or two depending on the value of foo when the function is evaluated. Do you see the difference? The alternative changes more frequently. Only you can say which of these meets your needs.

like image 194
Rory Daulton Avatar answered Sep 30 '22 12:09

Rory Daulton