Using Dictionary get method to return empty list by default returns None instead

Question:

In Python I would like to build up an dictionary of arrays using the dictionary get method to by default supply an empty list to then populate with information e.g.:

dct = {}
for i in range(0, 10):
    for j in range(0, 100):
        dct[i] = dct.get(i, []).append(j)

However when I try the above code I get no exceptions but my list ends up like the following:

AttributeError: ‘NoneType’ object has no attribute ‘append’

Lists have an append method, so I simplified my test to the following:

dct = {}
for i in range(0, 10):
    dct[i] = dct.get(i, []).append(i)

And the output was the following:

{0: None, 1: None, 2: None, 3: None, 4: None, 5: None, 6: None, 7: None, 8: None, 9: None}

So my question is why is dct.get(i, []) returning None by default and not []? Doing dct.get(i, list()) has the same problem, so I am a bit stumped.

Asked By: Danielb

||

Answers:

To solve this you should use Python’s defaultdict. The first time you use a key that doesn’t exist, the argument to the defaultdict constructor is used to create a value (in this case, a list).

http://docs.python.org/library/collections.html#defaultdict-examples

from collections import defaultdict 

d = defaultdict(list)
for i in range( 0, 10 ):
    for j in range( 0, 100 ):
        d[i].append( j )

You can also pass a function as the argument to defaultdict if you want to do anything more elaborate.

Answered By: Steve Mayne

append doesn’t return a list. It appends the value to the list and returns None.

Instead of this:

 dict[i] = dict.get( i, [] ).append( j ) 

You could do this:

 dict.setdefault(i, [])
 dict[i].append( j )
Answered By: eduffy

The problem is that append returns None instead of the list object. So

dict[i] = dict.get( i, [] ).append( j ) assigns None to dict[i]

However, you can do much simpler:

dict.setdefault( i, [] ).append( j )

.. quoting the docs for setdefault:

If key is in the dictionary, return its value. If not, insert key with a value of default and return default

So if the key i is not yet present it creates it and stores the default value in it, in either case it returns the key value – which is a reference to the list, so you can modify it directly.

Answered By: Alexander Gessler

It’s not dict.get( i, [] ) that’s returning None, it’s append. You probably want to use dict.setdefault(i, []).append(j) or just use a defaultdict in the first place.

Here’s how you would do it:

d = {}
for i in range( 0, 10 ):
    for j in range( 0, 100 ):
        d.setdefault( i, [] ).append( j )

Note that I changed dict to d because dict already means something in Python (you’re redefining it) and I removed the superfluous dict[i] = that was causing the error message.

Answered By: Gabe

An alternative that uses the get method by taking advantage of list addition.

d = {}
for i in range(0, 10):
    for j in range(0, 100):
        d[i] = d.get(i, []) + [j]
Answered By: yardsale8
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.