The Python Oracle

Pythonic way to avoid "if x: return x" statements

--------------------------------------------------
Hire the world's top talent on demand or became one of them at Toptal: https://topt.al/25cXVn
and get $2,000 discount on your first invoice
--------------------------------------------------

Music by Eric Matyas
https://www.soundimage.org
Track title: Over a Mysterious Island

--

Chapters
00:00 Pythonic Way To Avoid &Quot;If X: Return X&Quot; Statements
00:48 Accepted Answer Score 284
01:38 Answer 2 Score 399
02:06 Answer 3 Score 91
02:20 Answer 4 Score 75
03:01 Thank you

--

Full question
https://stackoverflow.com/questions/3611...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python #ifstatement

#avk47



ANSWER 1

Score 399


Chain or statements. This will return the first truthy value, or None if there's no truthy value:

def check_all_conditions():
    return check_size() or check_color() or check_tone() or check_flavor() or None

Split it into multiple lines like this:

def check_all_conditions():
    return (
        check_size()
        or check_color()
        or check_tone()
        or check_flavor()
        or None
    )

Demo:

>>> x = [] or 0 or {} or -1 or None
>>> x
-1
>>> x = [] or 0 or {} or '' or None
>>> x is None
True



ACCEPTED ANSWER

Score 284


You could use a loop:

conditions = (check_size, check_color, check_tone, check_flavor)
for condition in conditions:
    if result := condition():
        return result

This has the added advantage that you can now make the number of conditions variable.

Note that the above example uses an assignment expression (aka the walrus expression) to integrate the asignment and result test; this requires Python 3.8 or newer.

You could use map() + filter() to get the first such matching value, and, as of Python 3.11, operator.call():

try:  # python 3.11
    from operator import call
except ImportError:  # older versions
    def call(callable):
        return callable()

conditions = (check_size, check_color, check_tone, check_flavor)
return next(filter(None, map(call, conditions)), None)

but if this is more readable is debatable.

Another option is to use a generator expression:

conditions = (check_size, check_color, check_tone, check_flavor)
checks = (condition() for condition in conditions)
return next((check for check in checks if check), None)



ANSWER 3

Score 91


Don't change it

There are other ways of doing this as the various other answers show. None are as clear as your original code.




ANSWER 4

Score 75


According to Curly's law, you can make this code more readable by splitting two concerns:

  • What things do I check?
  • Has one thing returned true?

into two functions:

def all_conditions():
    yield check_size()
    yield check_color()
    yield check_tone()
    yield check_flavor()

def check_all_conditions():
    for condition in all_conditions():
        if condition:
            return condition
    return None

This avoids:

  • complicated logical structures
  • really long lines
  • repetition

...while preserving a linear, easy to read flow.

You can probably also come up with even better function names, according to your particular circumstance, which make it even more readable.