''' From https://github.com/makinacorpus/easydict. ''' class EasyDict(dict): """ Get attributes >>> d = EasyDict({'foo':3}) >>> d['foo'] 3 >>> d.foo 3 >>> d.bar Traceback (most recent call last): ... AttributeError: 'EasyDict' object has no attribute 'bar' Works recursively >>> d = EasyDict({'foo':3, 'bar':{'x':1, 'y':2}}) >>> isinstance(d.bar, dict) True >>> d.bar.x 1 Bullet-proof >>> EasyDict({}) {} >>> EasyDict(d={}) {} >>> EasyDict(None) {} >>> d = {'a': 1} >>> EasyDict(**d) {'a': 1} Set attributes >>> d = EasyDict() >>> d.foo = 3 >>> d.foo 3 >>> d.bar = {'prop': 'value'} >>> d.bar.prop 'value' >>> d {'foo': 3, 'bar': {'prop': 'value'}} >>> d.bar.prop = 'newer' >>> d.bar.prop 'newer' Values extraction >>> d = EasyDict({'foo':0, 'bar':[{'x':1, 'y':2}, {'x':3, 'y':4}]}) >>> isinstance(d.bar, list) True >>> from operator import attrgetter >>> map(attrgetter('x'), d.bar) [1, 3] >>> map(attrgetter('y'), d.bar) [2, 4] >>> d = EasyDict() >>> d.keys() [] >>> d = EasyDict(foo=3, bar=dict(x=1, y=2)) >>> d.foo 3 >>> d.bar.x 1 Still like a dict though >>> o = EasyDict({'clean':True}) >>> o.items() [('clean', True)] And like a class >>> class Flower(EasyDict): ... power = 1 ... >>> f = Flower() >>> f.power 1 >>> f = Flower({'height': 12}) >>> f.height 12 >>> f['power'] 1 >>> sorted(f.keys()) ['height', 'power'] """ def __init__(self, d=None, **kwargs): if d is None: d = {} if kwargs: d.update(**kwargs) for k, v in d.items(): setattr(self, k, v) # Class attributes for k in self.__class__.__dict__.keys(): if not (k.startswith('__') and k.endswith('__')): setattr(self, k, getattr(self, k)) def __setattr__(self, name, value): if isinstance(value, (list, tuple)): value = [self.__class__(x) if isinstance(x, dict) else x for x in value] elif isinstance(value, dict) and not isinstance(value, self.__class__): value = self.__class__(value) super(EasyDict, self).__setattr__(name, value) super(EasyDict, self).__setitem__(name, value) __setitem__ = __setattr__ def load_json(filename): import json with open(filename) as f: return EasyDict(json.load(f)) if __name__ == "__main__": import doctest doctest.testmod()