1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
|
'An ordered dictionary with attribute-style access.'
from collections import OrderedDict, Counter, defaultdict
# Python 3.5 does not allow inheriting from both OrderedDict and defaultdict.
# So we replace the default C implementation of OrderedDict with a pure Python
# version that's available in Python 3.5.
try:
class _test_multi_inheritance(OrderedDict, defaultdict):
pass
del _test_multi_inheritance
except TypeError:
from .ordereddict import OrderedDict
class AttrDict(OrderedDict):
'''
AttrDict extends OrderedDict to provide attribute-style access.
Items starting with __ or _OrderedDict__ can't be accessed as attributes.
'''
__exclude_keys__ = set()
def __getattr__(self, name):
'''Getting ad.x gets ad["x"]'''
if (name.startswith('__') or name.startswith('_OrderedDict__') or
name in self.__exclude_keys__):
return super(AttrDict, self).__getattr__(name)
else:
try:
return self[name]
except KeyError:
raise AttributeError(name)
def __setattr__(self, name, value):
'''Setting ad.x sets ad["x"]'''
if (name.startswith('__') or name.startswith('_OrderedDict__') or
name in self.__exclude_keys__):
return super(AttrDict, self).__setattr__(name, value)
self[name] = value
def __delattr__(self, name):
'''Deleting ad.x deletes ad["x"]'''
if (name.startswith('__') or name.startswith('_OrderedDict__') or
name in self.__exclude_keys__):
return super(AttrDict, self).__delattr__(name)
del self[name]
def __str__(self):
'''Print like a dict that is human readable'''
return '{' + ', '.join('%r: %r' % (key, val) for key, val in self.items()) + '}'
class CounterAttrDict(AttrDict, Counter):
'''
A Counter with ordered keys and attribute-style access
'''
def __init__(self, *args, **kwargs):
super(AttrDict, self).__init__(*args, **kwargs)
super(Counter, self).__init__(*args, **kwargs)
self.__exclude_keys__ |= {'most_common', 'elements', 'subtract'}
class DefaultAttrDict(AttrDict, defaultdict):
'''
A defaultdict with ordered keys and attribute-style access.
'''
def __init__(self, default_factory, *args, **kwargs):
super(AttrDict, self).__init__(*args, **kwargs)
defaultdict.__init__(self, default_factory)
self.__exclude_keys__ |= {'default_factory', '_ipython_display_'}
class Tree(DefaultAttrDict):
'''
A tree structure that lets you set attributes at any level.
'''
def __init__(self, *args, **kwargs):
super(Tree, self).__init__(Tree, *args, **kwargs)
|