Should I Return None or (None, None)?

PythonPython 3.xCoding Style

Python Problem Overview


We have a object method that returns a city/state tuple, i.e. ('Boston', 'MA'). Under some valid circumstances, there is no valid city/state to return. Stylistically, does it make more sense to return None, or a two element tuple containing (None, None) in that case?

Python Solutions


Solution 1 - Python

I would return None. If there is no result, why return something that looks like a result?

It is also easier to test:

result = getCity()
if result:
   # do something

I would only return (None, None) if it were possible that only one of the two values is None (i.e. ('Boston', None)). It would be more consistent in this case.

Solution 2 - Python

By only returning one value in exceptional circumstances, you risk breaking the tuple unpacking idiom. Some of your callers might issue:

city, state = getCityStateTuple("something")

In that case, returning None will break the caller with the error:

TypeError: 'NoneType' object is not iterable

So, I personally would return (None, None) in your situation. Then again, your mileage may vary, and it depends on the pattern used by your callers.

Solution 3 - Python

(None, None) does not evaluate to False in Python. In addition, building a tuple requires more work than, well, not building a tuple. So I would prefer None.

Solution 4 - Python

As others have noted, a tuple with items in it does not test as False, which is one reason you might want to return None rather than (None, None). However, it is possible to write a tuple subclass that tests as False even when it has items in it by overriding its __nonzero__() method.

class falsetuple(tuple):
    def __nonzero__(self):
        return False

Then you could return falsetuple((None, None)) when there is no value available. In fact, you could always return the same falsetuple.

I'm not necessarily recommending that you do this, in fact I have serious misgivings about flouting this convention, I'm just saying that the truthiness of non-empty tuples is not necessarily in itself a reason to not return a tuple.

Solution 5 - Python

If your routine normally returns a tuple, then a tuple is what it should keep returning. The real choice is between returning (None, None), or raising an exception, and we don't have enough information to offer good advice on that.

If it were me, and I chose the tuple over the exception, I would go with the FalseTuple that kindall suggests, and also realize that the calling code (which is using tuple unpacking) can also test

if city is None:

to see if a valid result was obtained. This way you are supporting tuple extraction across all possible return values, and still allowing the pythonic idiom of asking the object, "Do you evaluate as True?" (Here is kindall's again for completeness):

class FalseTuple(tuple):
    def __nonzero__(self):
        return False

Solution 6 - Python

why not making State a property of City? That way your function would return always one value: a City or None.

Returning (None, None) is bad for all the reasons stated in the other answers and serves only to support tuple unpacking.

None is the best value to return to state that no valid city can be returned, but having a function returning 1 or 2 values is not that good, again because of tuple unpacking.

Solution 7 - Python

To me, returning (None, None) would imply that (None, State) or (City, None) would also be valid return values. If that is the case, go with (None, None), otherwise, Felix and Brent provide very good arguments for simply returning None.

Solution 8 - Python

I would implement a public method for object that returned, let say isValidLocation() that returns true if location is valid and false if location is none.

Solution 9 - Python

If you return None, it will be much easier for you to check the return value.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questiondave mankoffView Question on Stackoverflow
Solution 1 - PythonFelix KlingView Answer on Stackoverflow
Solution 2 - PythonFrédéric HamidiView Answer on Stackoverflow
Solution 3 - PythonBrent NeweyView Answer on Stackoverflow
Solution 4 - PythonkindallView Answer on Stackoverflow
Solution 5 - PythonEthan FurmanView Answer on Stackoverflow
Solution 6 - PythonftartaggiaView Answer on Stackoverflow
Solution 7 - PythonJS.View Answer on Stackoverflow
Solution 8 - Pythonuser784540View Answer on Stackoverflow
Solution 9 - PythonChrisView Answer on Stackoverflow