The Python Oracle

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

Become part of the top 3% of the developers by applying to Toptal https://topt.al/25cXVn

--

Music by Eric Matyas
https://www.soundimage.org
Track title: Thinking It Over

--

Chapters
00:00 Question
01:01 Accepted answer (Score 283)
01:58 Answer 2 (Score 398)
02:24 Answer 3 (Score 91)
02:42 Answer 4 (Score 88)
02:59 Thank you

--

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

Accepted answer links:
[map()]: https://docs.python.org/3/library/functi...
[filter()]: https://docs.python.org/3/library/functi...
[future_builtins]: https://docs.python.org/2/library/future...

--

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.