Python how to use defaultdict fromkeys to generate a dictionary with predefined keys and empty lists

python

Solution

The `.fromkeys` method is primarily used to set a dict to a single same default value:

>>> {}.fromkeys(['a','b','c'])
{'a': None, 'c': None, 'b': None}

It does not call a function for each key (which is what `list` or `[]` is).

Default dict needs a 'factory function' to be a default dict:

>>> from collections import defaultdict
>>> result=defaultdict(list)
>>> result
defaultdict(<type 'list'>, {})

The factory function (in this case, `list`) is called any time a missing key is added to a defaultdict to form the default value.

So to set three lists with keys `'a','b','c'` you would do:

>>> for e in ('a','b','c'):
...    result[e]       # 'e' is not in the dict, so it is added 
                       #    and a new list is the value 
>>> result
defaultdict(<type 'list'>, {'a': [], 'c': [], 'b': []})

Or, you can use the `.update` method as Raymond Hettinger points out:

>>> result=defaultdict(list)
>>> result.update((k,[]) for k in 'abc')
>>> result
defaultdict(<type 'list'>, {'a': [], 'c': [], 'b': []})  

Or, as `ivan_pozdeev` points out in comments, you can do:

>>> di=defaultdict(list,{k:[] for k in 'abc'})
>>> di
defaultdict(<type 'list'>, {'a': [], 'c': [], 'b': []})  

Or you can use a regular Python dict with a dict comprehension to get the same thing -- no defaultdict required -- if you only need or want those three keys with unique lists as their values:

>>> di={k:[] for k in 'abc'}
>>> di
{'a': [], 'c': [], 'b': []}

And those are separate lists for each key:

>>> di['a'].append(1)
>>> di
{'a': [1], 'c': [], 'b': []}

A common mistake (which I have made ;-0) is to use something like `.fromkeys` and get the same list referred to by multiple keys:

>>> di2={}.fromkeys(['a','b','c'], [])
>>> di2
{'a': [], 'c': [], 'b': []}      # looks ok
>>> di2['a'].append('WRONG!')
>>> di2
{'a': ['WRONG!'], 'c': ['WRONG!'], 'b': ['WRONG!']}

Happens because the same single list is referred to by all the keys.

Problem

Here is the code: ``` from collections import defaultdict result = defaultdict.fromkeys(['a','b','c'], list) result['a'].append(1) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-44-6c01c8d56a42> in <module>() ----> 1 result['a'].append('1') TypeError: descriptor 'append' requires a 'list' object but received a 'str' ``` I don't understand the error message, what went wrong and how to fix it?

Original source