Spaces:
Runtime error
Runtime error
| """ | |
| EasyDict | |
| Copy/pasted from https://github.com/makinacorpus/easydict | |
| Original author: Mathieu Leplatre <[email protected]> | |
| """ | |
| 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} | |
| >>> EasyDict((('a', 1), ('b', 2))) | |
| {'a': 1, 'b': 2} | |
| 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 | |
| >>> list(map(attrgetter('x'), d.bar)) | |
| [1, 3] | |
| >>> list(map(attrgetter('y'), d.bar)) | |
| [2, 4] | |
| >>> d = EasyDict() | |
| >>> list(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}) | |
| >>> list(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'] | |
| update and pop items | |
| >>> d = EasyDict(a=1, b='2') | |
| >>> e = EasyDict(c=3.0, a=9.0) | |
| >>> d.update(e) | |
| >>> d.c | |
| 3.0 | |
| >>> d['c'] | |
| 3.0 | |
| >>> d.get('c') | |
| 3.0 | |
| >>> d.update(a=4, b=4) | |
| >>> d.b | |
| 4 | |
| >>> d.pop('a') | |
| 4 | |
| >>> d.a | |
| Traceback (most recent call last): | |
| ... | |
| AttributeError: 'EasyDict' object has no attribute 'a' | |
| """ | |
| def __init__(self, d=None, **kwargs): | |
| if d is None: | |
| d = {} | |
| else: | |
| d = dict(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('__')) and not k in ('update', 'pop'): | |
| 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 update(self, e=None, **f): | |
| d = e or dict() | |
| d.update(f) | |
| for k in d: | |
| setattr(self, k, d[k]) | |
| def pop(self, k, d=None): | |
| delattr(self, k) | |
| return super(EasyDict, self).pop(k, d) | |
| if __name__ == "__main__": | |
| import doctest | |
| doctest.testmod() |