Using Dictionary get method to return empty list by default returns None instead
Solution 1
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.
Solution 2
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.
Solution 3
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.
Solution 4
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 )
Solution 5
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]
Related videos on Youtube
Comments
-
Danielb almost 2 years
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, [])
returningNone
by default and not[]
? Doingdct.get(i, list())
has the same problem, so I am a bit stumped.-
Nicholas Knight about 13 yearsPlease please please do not use
dict
as a variable name. It clashes with the built-indict
class. -
DanielbI don't typically do that, I just wanted to be clear as to what the variable was.
-
Steve MayneYour first setdefault code is flawed, don't assign back to dict[i].
dict.setdefault( i, [] ).append( j )
should be all you need. -
GabeYou don't want the
dict[i] =
in front of thesetdefault
. See my edited answer. -
DanielbYour correct, I just figured that out. May thanks, I wish I could make you all as correct :(
-
-
Danielb about 13 yearsDoing the append and setdefault on the same line caused an exception for me on Python 2.7.1.
-
Steve Mayne about 13 yearsor, on one line:
dict.setdefault(i, []).append( j )
- although it should be noted that defaultdict is faster. -
Alexander Gessler about 13 yearsWorks for me with both 2.6 and 3.1
-
jwg almost 9 yearsThis is the right answer. There are no bonus points in Python for 'rolling your own'.
-
martineau almost 9 yearsProblem is this requires first making a one element list out of
j
in order to take advantage of it.