Is it Pythonic to return True and None vs True and False?

Viewed 463

Has this style of coding become Pythonic? Is it recommended by people in the Python community? I saw someone use it recently and it surprised me.

def is_forty_two(val):
    if val == 42:
        return True

It returns True or None, instead of True or False. Because bool(None) == False, this sort of code works in most places you would want to use it.

But to me, this is obviously a very dangerous coding style. My bug detector goes off when I see code that mixes return values and running off the end without a declared return value. But maybe I'm wrong? Testing this code in PyCharm I see that PyCharm doesn't flag an issue and it shows the return type of the function as "-> bool"???

When I add a return None at the end, which has doesn't change how it works, PyCharm then shows the return type as the expected "Optional[bool]".

Is it a bug (or lack of complexity in PyCharm to catch this?)

Or has this style become "acceptable" in Python?

I would write it as the obvious simpler form:

def is_some_test(val):
    return val == 42

Or if the test was more complex or maybe a string of if and else, I would use a style like this:

def is_some_test(val):
    if complex_test1(val):
        return True
    if complex_test2(val):
        return True
    return False

I would never intentionally allow a function to return True/None instead of True/False. And as a long-time matter of coding style (From decades of C programming), any function that returns an explicit value I always structure the code so it ends with an explicit return statement as the last line of function.

3 Answers

I can't answer objectively what code is Pythonic as that can easily devolve into opinion. But, consider the statement

print(False == None)

Which prints false, so they are not the same. So, I don't see how they can be substituted for each other.

This is not Pythonic, since this violates the rule "Explicit is better than implicit". As a general rule, return True or False for a method whose naming convention and apparent code indicate a boolean return value. None is not a substitute for False.

Also, consider these:

# As expected:
print(False is False)
# True

print(False == False)
# True

# If the result of the function is 'None', it has to be cast to 'bool'
# before comparing to 'False':
print(False is None)
# False

print(False == None)
# False

print(False is bool(None))
# True

print(False == bool(None))
# True

SEE ALSO:
Python Docs: Built-in Constants: https://docs.python.org/library/constants.html
Python Docs: Built-in Types: Truth Value Testing: https://docs.python.org/library/stdtypes.html#truth-value-testing

The proposed solution force the code that uses the function to manage different returns type (bool or None). Not sure what is the benefit.

I suggest adding typings (if possible) to facilitate the reading/debugging:

def is_forty_two(val: int) -> bool:
    return val == 42
Related