101
votes

How can I convert a defaultdict

number_to_letter
defaultdict(<class 'list'>, {'2': ['a'], '3': ['b'], '1': ['b', 'a']})

to be a common dict?

{'2': ['a'], '3': ['b'], '1': ['b', 'a']}
3
dict(number_to_letter) - Tim Peters
@TimPeters since this is actually a nicely written question, with an obvious title (and should show up easily in searches), for future reference it'd be worth putting that as an answer if we can't find a dupe that's better... - Jon Clements♦
This answer should help: stackoverflow.com/a/3031915/1628832 - karthikr
@JonClements, good point, but DSM already did - I hope his answer is accepted :-) - Tim Peters
@TimPeters congrats on the 10k btw... I had a feeling it wouldn't take you long - you should (shameless plug) pop by chat.stackoverflow.com/rooms/6/python at some point :) - Jon Clements♦

3 Answers

131
votes

You can simply call dict:

>>> a
defaultdict(<type 'list'>, {'1': ['b', 'a'], '3': ['b'], '2': ['a']})
>>> dict(a)
{'1': ['b', 'a'], '3': ['b'], '2': ['a']}

but remember that a defaultdict is a dict:

>>> isinstance(a, dict)
True

just with slightly different behaviour, in that when you try access a key which is missing -- which would ordinarily raise a KeyError -- the default_factory is called instead:

>>> a.default_factory
<type 'list'>

That's what you see when you print a before the data side of the dictionary appears.

So another trick to get more dictlike behaviour back without actually making a new object is to reset default_factory:

>>> a.default_factory = None
>>> a[4].append(10)
Traceback (most recent call last):
  File "<ipython-input-6-0721ca19bee1>", line 1, in <module>
    a[4].append(10)
KeyError: 4

but most of the time this isn't worth the trouble.

30
votes

If your defaultdict is recursively defined, for example:

from collections import defaultdict
recurddict = lambda: defaultdict(recurddict)
data = recurddict()
data["hello"] = "world"
data["good"]["day"] = True

yet another simple way to convert defaultdict back to dict is to use json module

import json
data = json.loads(json.dumps(data))

and of course, the values contented in your defaultdict need to be confined to json supported data types, but it shouldn't be a problem if you don't intent to store classes or functions in the dict.

15
votes

If you even want a recursive version for converting a recursive defaultdict to a dict you can try the following:

#! /usr/bin/env python3

from collections import defaultdict

def ddict():
    return defaultdict(ddict)

def ddict2dict(d):
    for k, v in d.items():
        if isinstance(v, dict):
            d[k] = ddict2dict(v)
    return dict(d)

myddict = ddict()

myddict["a"]["b"]["c"] = "value"

print(myddict)

mydict = ddict2dict(myddict)

print(mydict)