From 8b0250eca4e2e7dfaa48d5a4a96524adc571578d Mon Sep 17 00:00:00 2001 From: Andreas Date: Wed, 21 Oct 2009 21:44:27 +0000 Subject: [PATCH] dictionary with attribute member access --HG-- branch : aspn --- src/attrdict.py | 92 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 67 insertions(+), 25 deletions(-) diff --git a/src/attrdict.py b/src/attrdict.py index f3f4178..e11b0b5 100644 --- a/src/attrdict.py +++ b/src/attrdict.py @@ -1,33 +1,75 @@ +# Copyright (c) 2009 Andreas Balogh +# See LICENSE for details. + +# http://code.activestate.com/recipes/361668/ # http://code.activestate.com/recipes/473786/ +# http://groups.google.com/group/comp.lang.python/browse_thread/thread/fa88bba7184d9431 class AttrDict(dict): - """A dictionary with attribute-style access. It maps attribute access to + """A dict whose items can also be accessed as member variables. + + A dictionary with attribute-style access. It maps attribute access to the real dictionary. """ - def __init__(self, init={}): - dict.__init__(self, init) - - def __getstate__(self): - return self.__dict__.items() - - def __setstate__(self, items): - for key, val in items: - self.__dict__[key] = val - - def __repr__(self): - return "%s(%s)" % (self.__class__.__name__, dict.__repr__(self)) - - def __setitem__(self, key, value): - return super(AttrDict, self).__setitem__(key, value) - - def __getitem__(self, name): - return super(AttrDict, self).__getitem__(name) - - def __delitem__(self, name): - return super(AttrDict, self).__delitem__(name) - - __getattr__ = __getitem__ - __setattr__ = __setitem__ + def __init__(self, *args, **kwargs): + dict.__init__(self, *args, **kwargs) + self.__dict__ = self def copy(self): ch = AttrDict(self) return ch + + def __repr__(self): + return 'AttrDict(' + dict.__repr__(self) + ')' + + @classmethod + def fromkeys(self, seq, value = None): + return AttrDict(dict.fromkeys(seq, value)) + + +if __name__ == "__main__": + # test cases provided by Gabriel Genellina + from pickle import loads, dumps + assert AttrDict() == {} + d1 = {1:2, '3':4, 'name': 'value', '__getattr__': 5, '__getitem__': 6} + d2 = AttrDict(d1) + assert d1 == d2 + + assert d2.copy() == d2 + assert isinstance(d2.copy(), type(d2)) + assert eval(repr(d2)) == d2 + assert isinstance(eval(repr(d2)), type(d2)) + + d3 = AttrDict.fromkeys([1,2,3]) + assert isinstance(d3, AttrDict) + assert d3 == {1:None, 2:None, 3:None} + + assert d2[1] == 2 + assert d2['name'] == d2.name == 'value' + assert d2.__getattr__ == 5 + + assert not hasattr(d2, 'xyz') + assert 'xyz' not in d2 + d2.xyz = 123 + assert d2.xyz == d2['xyz'] == 123 + assert 'xyz' in d2 + + d2['xyz'] = 456 + assert d2['xyz'] == d2.xyz == 456 + assert hasattr(d2, 'xyz') + + d2['abc'] = 789 + assert d2.abc == d2['abc'] == 789 + + d2.abc = 123 + assert d2.abc == d2['abc'] == 123 + + del d2.abc + assert not hasattr(d2, 'abc') + assert 'abc' not in d2 + del d2['xyz'] + assert not hasattr(d2, 'xyz') + assert 'xyz' not in d2 + + d4 = loads(dumps(d2)) + assert d2 == d4 + assert isinstance(d4, type(d2)) \ No newline at end of file