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?
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.
Unfortunately, fromkeys() is for setting the same value over and over again. It isn't helpful when you need distinct lists.
So, I would tackle the problem like this:
>>> keys = ['barry', 'tim', 'fredrik', 'alex']
>>> d = defaultdict(list)
>>> d.update((k, []) for k in keys)
>>> d
defaultdict(<class 'list'>, {'barry': [], 'tim': [], 'fredrik': [], 'alex': []})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With