Note
- Source code at https://github.com/bunbun/nested-dict
- Documentation at http://nested-dict.readthedocs.org
nested_dict
¶
nested_dict
is a drop-in replacement extending python dict and defaultdict with multiple levels of nesting.You can created a deeply nested data structure without laboriously creating all the sub-levels along the way:
>>> nd= nested_dict() >>> # magic >>> nd["one"][2]["three"] = 4Each nested level is created magically when accessed, a process known as “auto-vivification” in perl.
Specifying the contained type¶
Examples:
dict of list
s¶
# nested dict of lists nd = nested_dict(2, list) nd["mouse"]["2"].append(12) nd["human"]["1"].append(12)
dict of set
s¶
# nested dict of sets nd = nested_dict(2, set) nd["mouse"]["2"].add("a") nd["human"]["1"].add("b")
dict of int
s¶
# nested dict of ints nd = nested_dict(2, int) nd["mouse"]["2"] += 4 nd["human"]["1"] += 5 nd["human"]["1"] += 6 nd.to_dict() #{'human': {'1': 11}, 'mouse': {'2': 4}}
dict of str
s¶
# nested dict of strings nd = nested_dict(2, str) nd["mouse"]["2"] += "a" * 4 nd["human"]["1"] += "b" * 5 nd["human"]["1"] += "c" * 6 nd.to_dict() #{'human': {'1': 'bbbbbcccccc'}, 'mouse': {'2': 'aaaa'}}
Iterating through nested_dict
¶
Iterating through deep or unevenly nested dictionaries is a bit of a pain without recursion.
nested dict
allows you to flatten the nested levels into tuples before iteration.
You do not need to know beforehand how many levels of nesting you have:
from nested_dict import nested_dict nd= nested_dict() nd["one"] = "1" nd[1]["two"] = "1 / 2" nd["uno"][2]["three"] = "1 / 2 / 3" for keys_as_tuple, value in nd.items_flat(): print ("%-20s == %r" % (keys_as_tuple, value)) # (1, 'two') == '1 / 2' # ('one',) == '1' # ('uno', 2, 'three') == '1 / 2 / 3'
- nested_dict provides
(iteritems_flat(), iterkeys_flat(), and itervalues_flat() are python 2.7-style synonyms. )
Converting to / from dict
¶
The magic of nested_dict
sometimes gets in the way (of pickleing for example).
- We can convert to and from a vanilla python
dict
using -
>>> from nested_dict import nested_dict >>> nd= nested_dict() >>> nd["one"] = 1 >>> nd[1]["two"] = "1 / 2" # # convert nested_dict -> dict and pickle # >>> nd.to_dict() {1: {'two': '1 / 2'}, 'one': 1} >>> import pickle >>> binary_representation = pickle.dumps(nd.to_dict()) # # convert dict -> nested_dict # >>> normal_dict = pickle.loads(binary_representation) >>> new_nd = nested_dict(normal_dict) >>> nd == new_nd True
Updating with another dictionary¶
You can use the
nested_dict.update(other)
method to merge in the contents of another dictionary.If the
nested_dict
has a fixed nesting and a value type, then key / value pairs will be overridden from the other dict like in Python’s standard librarydict
. Otherwise they will be preserved as far as possible.For example, given a three-level nested
nested_dict
ofint
:>>> d1 = nested_dict.nested_dict(3, int) >>> d1[1][2][3] = 4 >>> d1[1][2][4] = 5 >>> # integers have a default value of zero >>> default_value = d1[1][2][5] >>> print (default_value) 0 >>> print (d1.to_dict()) {1: {2: {3: 4, 4: 5, 5:0}}}We can update this with any dictionary, not necessarily a three level
nested_dict
ofint
.>>> # some other nested_dict >>> d2 = nested_dict.nested_dict() >>> d2[2][3][4][5] = 6 >>> d1.update(d2) >>> print (d1.to_dict()) {1: {2: {3: 4, 4: 5, 5: 0}}, 2: {3: {4: {5: 6}}}}However, the rest of the dictionary maintains has the same default value type at the specified level of nesting
>>> print (d1[2][3][4][5]) 6 >>> # d1[2][3][???] == int() even though d1[2][3][4][5] = 6 >>> print (d1[2][3][5]) 0
defaultdict
¶
nested_dict
extends collections.defaultdict
You can get arbitrarily-nested “auto-vivifying” dictionaries using defaultdict.
from collections import defaultdict nested_dict = lambda: defaultdict(nested_dict) nd = nested_dict() nd[1][2]["three"][4] = 5 nd["one"]["two"]["three"][4] = 5
However, only nested_dict
supports a dict
of dict
of sets
etc.