# 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 """ Looks fine as long as nobody uses an existing method name as a dictionary key: py> d = AttrDict({'name':'value'}) py> d.items() [('name', 'value')] py> d = AttrDict({'items': [1,2,3]}) py> d.items() Traceback (most recent call last): File "", line 1, in TypeError: 'list' object is not callable (I should have included a test case for this issue too). Of course, if this doesn't matter in your application, go ahead and use it. Just be aware of the problem. """ class AttrDict(dict): """A dict whose items can also be accessed as member variables.""" 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))