Thesaurus: A different way to call a dictionary. Thesaurus is a new a dictionary subclass which allows calling keys as if they are class attributes and will search through nested objects recursively when __getitem__ is called.
You will notice that the code is disgusting simple. However I have found that this has completely changed the way I program in python. I've re-written some exiting programs using Thesaurus, and often realized 15-30% code reduction. Additionally I find the new code much easier to read. If you find yourself programing with nested dictionaries often, fighting to generate output or command lines for external programs, or wish you had a dictionary that could act (sort of) like a class, Thesaurus may be for you.
#!/usr/bin/env python """ thesaurus.py 2012-09-13 Copyright (c) 2012 Dave Cinege Licence: python, Copyright notice may not be altered. Thesaurus: A different way to call a dictionary. Thesaurus is a new a dictionary subclass which allows calling keys as if they are class attributes and will search through nested objects recursivly when __getitem__ is called. You will notice that the code is disgusting simple. However I have found that this has completely changed the way I program in python. I've re-written some exiting programs using Thesaurus, and often relized 15-30% code reduction. Additionally I find the new code much easier to read. If you find yourself programing with nested dictionaries often, fighting to generate output or command lines for external programs, or wish you had a dictionary that could act (sort of) like a class, Thesaurus may be for you. By example: --------------- #!/usr/bin/env python import thesaurus thes = thesaurus.Thesaurus # I like to create a master global object called 'g'. # No more 'global' statements for me. g = thes() g.prog = thes() g['prog']['VERSION'] = '1.0' # I can do this like a normal nested dictionary g.prog.VERSION = '1.0' # But isn't this so much cleaner? g.prog.NAME = 'Thesaurus' class TestClass: no = 'Class' way = 'this' def main (): L = thes() # Some local varibles L.tc = TestClass() # We can also recurse to class attributes L.l = list() # And recurse to indices too! L.l.append('Some') L.l.append('objects') g.L = L # Easily make these locals global # Here's the real magic. Creating output without a fight. print ''' When programing python using %(prog.NAME)s, it is very easy to access your %(L.l.1)s. %(L.l.0)s people might say %(prog.NAME)s has no %(L.tc.no)s. '''.replace('\t','')[1:-1] % g del g.L # Clean locals up out of global space # If I was using a storage class, I must use hasattr() or an ugly eval. # But we can still use a str for the key name and 'in' like on any # regular dictionary. if 'VERSION' in g.prog: print 'But I challenge them to write code %(tc.way)s clean without it!' % L if __name__ == '__main__': main() --------------- """ __VERSION__ = 20120913 class Thesaurus (dict): def __getattr__(self, name): return self.__getitem__(name) def __setattr__(self, name, value): return dict.__setitem__(self, name, value) def __delattr__(self, name): return dict.__delitem__(self, name) def __getitem__(self, key): if '.' not in key: return dict.__getitem__(self, key) l = key.split('.') if isinstance(l[0], (dict, Thesaurus)): a = self.data else: a = self for i in range(len(l)): # Walk keys recursivly try: a = a[l[i]] # Attempt key except: try: a = getattr(a, l[i]) # Attempt attr except: try: a = a[int(l[i])] # Attempt indice except: raise KeyError(key + ' [%s]' % i) return a
-- http://mail.python.org/mailman/listinfo/python-list