I don't know why you want to do this, this type of thing will become slow when the data structure size increases. It would probably be better to have a flat dictionary, however the algorithm for flattening has to be defined.
I've done something crude for what I think you want. The flatten
method returns something similar to items
(a list of (key, value) tuples) where the 'key' is actually a tuple of keys. This is necessary as a dictionaries may contain the same key and so when transformed onto a flat namespace (which requires unique keys), a conflict arises.
class recurdict(dict):
'''
Recursive Dictionary
'''
def __init__(self, idict=None, **kwargs):
dict.__init__(self)
if idict is not None:
self.update(idict)
if len(kwargs):
self.update(kwargs)
def __contains__(self, key):
return (key in self.keys())
def __getitem__(self, key):
if self.__contains__(key):
return self.___getitem__(self, key)
else:
raise KeyError(key)
@staticmethod
def ___getitem__(idict, key):
if dict.__contains__(idict, key):
return dict.__getitem__(idict, key)
else:
result = None
for k, v in idict.iteritems():
if hasattr(v, "keys"):
result = recurdict.___getitem__(v, key)
if(result):
return result
else:
continue
def flatten(self):
return self._flatten(self)
@staticmethod
def _flatten(idict, key_chain = []):
found_keys = []
for k, v in idict.iteritems():
if hasattr(v, "keys"):
found_keys.extend(recurdict._flatten(v, key_chain + [k]))
else:
found_keys.append((tuple(key_chain + [k]), v))
return found_keys
def has_key(self, key):
return self.__contains__(key)
def keys(self):
return self._keys(self)
@staticmethod
def _keys(idict):
found_keys = dict.keys(idict)
for k, v in idict.iteritems():
if hasattr(v, "keys"):
found_keys.extend(recurdict._keys(v))
return found_keys
def update(self, other=None, **kwargs):
if other is None:
pass
elif hasattr(other, "iteritems"):
for k, v in other.iteritems():
self.__setitem__(k,v)
elif hasattr(other, "keys"):
for k in other.keys():
self.__setitem__(k,other.__getitem__(k))
else:
for k, v in other:
self.__setitem__(k,v)
if kwargs:
self.update(kwargs)
example_dict = recurdict\
({
"key1" : "value1",
"key2" : "value2",
"key3" :
{
"key3a": "value3a"
},
"key4" :
{
"key4a":
{
"key4aa": "value4aa",
"key4ab": "value4ab",
"key4ac":
{
"key4ac1": [0,1,2],
"key4ac2": (3,4,5),
"key4ac3":
[
{
"sub_key_x": 0,
"sub_key_y": 1,
},
6
]
}
},
"key4b": "value4b"
}
})
print example_dict.keys()
print "key1" in example_dict
print "key4ac1" in example_dict
print example_dict["key4ac1"]
for (k, v) in example_dict.flatten():
print (k, v)