0

I like using lambdas more then I should so more than once I wanted to solve nested if statement with it and failed using standard syntax.

But then I tried something like this:

lambda x: 1 if x > 100 else 2 if x > 50 else 3

Surprisingly it works, although proper function is supposed to have elif:

def foo(x):
    if x > 100:
        return 1
    elif x > 50:
        return 2
    else:
        return 3

Any ideas why?

3
  • 6
    I'd recommend lambda x: 1 if x > 100 else (2 if x > 50 else 3) for readability because explicit is better than implicit. Commented Aug 12, 2017 at 15:38
  • Why do you think a proper function should use elif? Commented Aug 12, 2017 at 15:42
  • @Gribouillis I wish you wrote that as an answer as it pretty much explains what and why :) Commented Aug 14, 2017 at 10:42

5 Answers 5

4

You don't have to use elif. You can use if inside another else which is the same as what lambda function is doing:

def foo(x):
    if x > 100:
        return 1
    else:
        if x > 50:
           return 2
        else:
           return 3
Sign up to request clarification or add additional context in comments.

3 Comments

I also like lambda x: 3 - bisect.bisect_left([50, 100], x) :-)
@Gribouillis Sure, if you are searching in an interval I think bisect is the way to go.
@ayhan I know how it functions and what is the flow but the syntax seemed strange
1

I'd recommend

lambda x: 1 if x > 100 else (2 if x > 50 else 3)

for readability because explicit is better than implicit.

Indeed, due to evaluation from left to right, the ternary operator is right associative as the following code demonstrates

def f(a, b):
    return 1 if a else 2 if b else 3

def left(a, b):
    return (1 if a else 2) if b else 3

def right(a, b):
    return 1 if a else (2 if b else 3)

tpl = "{:^8}{:^8}{:^6}{:^6}{:^6}"
print(tpl.format('a', 'b', 'f', 'left', 'right'))
for (a, b) in [(False, False),(False, True),(True, False),(True, True)]:
    print(tpl.format(repr(a), repr(b), f(a,b), left(a,b), right(a,b)))

""" my output ->

a       b      f    left right 
False   False    3     3     3   
False    True    2     2     2   
True   False    1     3     1   
True    True    1     1     1  

"""

The ternary expression always gives the same result as the expression where everything after the first else is parenthesized.

When the conditions are (x>100) and (x>50), the case True, False can never happen, so the three expressions give the same result. Nevertheless, explicit is better than implicit!

Comments

0

You are actually using something like elif by writing

else 2 if x > 50

in

lambda x: 1 if x > 100 else 2 if x > 50 else 3

Its just a different way of writing something like elif in lambda

Comments

0
lambda x: 1 if x > 100 else 2 if x > 50 else 3

Means :

# 1 if x > 100 
if x > 100:
    return 1 
# else 2 if x > 50 else 3
else:
    # 2 if x > 50 else 3
    if x > 50:
        return 2
    else:
        return 3

Which does the same thing that your second snippet with elif.

You cannot use elif in a lambda expression. As far as I know, it should raise a SyntaxError.

Comments

0

You have concatenated two conditional expressions.

One

2 if x > 50 else 3

provides the value for the else clause of the other.

1 if x > 100 else ...

You have the conditional expression

x if C else y

where

x = 1
C = 100

and

y = 2 if x > 50 else 3

From the docs, y can be an expression so y can be a conditional expression.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.