Should I return an empty dict instead of None?

Question:

I have a method that currently returns None or a dict.

result,error = o.apply('grammar')

The caller currently has to check for the existence of two keys to decide what kind of object was returned.

if 'imperial' in result:
    # yay
elif 'west' in result:
    # yahoo
else:
    # something wrong?

Because result can be None, I’m thinking of returning an empty dict instead, so the caller does not need to check for that. What do you think ?

For comparison, in the re module, the result of calling match can result in None.

p = re.compile('w+')
m = p.match( 'whatever' )

But in this case, m is an object instance. In my case, I am returning a dict which should either be empty or have some entries.

Asked By: Frankie Ribery

||

Answers:

After more thought, I think returning an empty dict might be more Pythonic. A good rule of thumb might be to always return an empty container if you write a function/method which returns a container. Several examples of this behavior:

"".split() == []
filter(lambda a:False, [1,2]) == []
range(1, -1) == []
re.findall('x', '') = []

In contrast if you are trying to get a single object, you have no choice but to return None I suppose. So I guess None is like the empty container for single objects! Thanks to KennyTM for arguing some sense into me 😀

Answered By: zeekay

Yes I think returning an empty dict (or where applicable an empty list) is preferable to returning None as this avoids an additional check in the client code.

EDIT:
Adding some code sample to elaborate:

def result_none(choice):
    mydict = {}
    if choice == 'a':
        mydict['x']  = 100
        mydict['y']  = 1000
        return mydict
    else:
        return None

def result_dict(choice):
    mydict = {}
    if choice == 'a':
        mydict['x']  = 100
        mydict['y']  = 1000
    return mydict

test_dict = result_dict('b')
if test_dict.get('x'):
    print 'Got x'
else:
    print 'No x'

test_none = result_none('b')
if test_none.get('x'):
    print 'Got x'
else:
    print 'No x'

In the above code the check test_none.get(x) throws an AttributeError as
result_none method can possibly return a None. To avoid that I have to add an
additional check and might rewrite that line as:
if test_none is not None and test_none.get('x') which is not at all needed
if the method were returning an empty dict. As the example shows the check test_dict.get('x') works fine as the method result_dict returns an empty dict.

Answered By: sateesh

As others have said, an empty dict is falsy, so there’s no problem there. But the idea of returning an empty dict leaves a bad taste in my mouth. I can’t help but feel that returning an empty dict could hide errors that returning None would reveal. Still, it’s just a gut feeling.

Answered By: senderle

I’m not entirely sure of the context of this code, but I’d say returning None suggests that there was somehow an error and the operation could not be completed. Returning an empty dictionary suggests success, but nothing matched the criteria for being added to the dictionary.

I come from a completely different background (C++ Game Development) so take this for what it’s worth:

For performance reasons though, might be nice to return None and save whatever overhead, though minimal, may be involved in creating an empty dictionary. I find that, generally, if you’re using a scripting language, you’re not concerned about the performance of that code. If you were, you probably wouldn’t be writing that feature in said language unless required for some unavoidable reason.

Answered By: Sion Sheevok
Python supports returning multiple values. Hence, you can return a status of success along with an empty dictionary. The caller first verifies the return code and then uses the dictionary.

def result_none(choice):
    mydict = {}
    retcode = -1
    if choice == 'a':
        mydict['x']  = 100
        mydict['y']  = 1000
        retcode = 0
    return mydict, retcode

retcode, mydict = result_none('a')
if retcode == 0:
   <<use dictionary>>
Answered By: Santhosh
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.