Object-like attribute access for nested dictionary
The following class would let you do what you want (works in Python 2 & 3):
class AttrDict(dict):
""" Dictionary subclass whose entries can be accessed by attributes (as well
as normally).
>>> obj = AttrDict()
>>> obj['test'] = 'hi'
>>> print obj.test
hi
>>> del obj.test
>>> obj.test = 'bye'
>>> print obj['test']
bye
>>> print len(obj)
1
>>> obj.clear()
>>> print len(obj)
0
"""
def __init__(self, *args, **kwargs):
super(AttrDict, self).__init__(*args, **kwargs)
self.__dict__ = self
@classmethod
def from_nested_dicts(cls, data):
""" Construct nested AttrDicts from nested dictionaries. """
if not isinstance(data, dict):
return data
else:
return cls({key: cls.from_nested_dicts(data[key]) for key in data})
if __name__ == '__main__':
data = {
"a": "aval",
"b": {
"b1": {
"b2b": "b2bval",
"b2a": {
"b3a": "b3aval",
"b3b": "b3bval"
}
}
}
}
data1 = AttrDict.from_nested_dicts(data)
print(data1.b.b1.b2a.b3b) # -> b3bval
Building on @martineau's excellent answer, you can make the AttrDict class to work on nested dictionaries without explicitly calling the from_nested_dict() function:
class AttrDict(dict):
""" Dictionary subclass whose entries can be accessed by attributes
(as well as normally).
"""
def __init__(self, *args, **kwargs):
def from_nested_dict(data):
""" Construct nested AttrDicts from nested dictionaries. """
if not isinstance(data, dict):
return data
else:
return AttrDict({key: from_nested_dict(data[key])
for key in data})
super(AttrDict, self).__init__(*args, **kwargs)
self.__dict__ = self
for key in self.keys():
self[key] = from_nested_dict(self[key])
Try Dotsi or EasyDict. They both support dot-notation for nested dicts.
>>> import dotsi
>>> data = dotsi.fy({'a': 'aval', 'b': {'b1':{'b2a':{'b3a':'b3aval','b3b':'b3bval'},'b2b':'b2bval'}} })
>>> print(data.b.b1.b2a.b3b)
b3bval
>>>
In addition to dicts-within-dicts, Dotsi also supports dicts-within-lists-within-dicts.
Note: I'm Dotsi's author.