Python LazyDict
I'm a great fan of the dot notation, instead of foo['bar'] hash notation. Also because the Django and Jinja templating engines use dot notation for all their object attribute/key lookups.
You can also use assignments and lookups on a dictionary, using the __setattr__ and __getattr__ methods:
class LazyDict(dict): def __getattr__(self, attr): if attr in self: return self[attr] else: raise AttributeError, "'%s' object has no attribute '%s'" \ % (self.__class__.__name__, attr) def __setattr__(self, attr, value): if hasattr(super(LazyDict, self), attr): raise AttributeError, "'%s' object already has attribute '%s'" \ % (self.__class__.__name__, attr) self[attr] = value
This allows you to do:
>>> from lazydict import LazyDict >>> foo = LazyDict() >>> foo.bar = 42 >>> foo.bar 42 >>> foo.biz = LazyDict() >>> foo.biz.qux Traceback (most recent call last): File "<stdin>", line 1, in <module> File "lazydict.py", line 6, in __getattr__ AttributeError: LazyDict instance has no attribute 'qux' >>> foo.biz.qux = object() >>> foo.biz.qux <object object at 0xb7d26468>
Update Nov 12, 1008
Incorporated Floes' suggestions from the comment below, thanks!
The code you have pasted now makes it an immutable dictionary of sorts:
>>> lazy = LazyDict() >>> lazy.foo = 'bar' >>> lazy.foo = 'baz' Traceback (most recent call last): File "<stdin>", line 1, in <module> File "tidbits.py", line 47, in __setattr__ % (self.__class__.__name__, attr) AttributeError: 'LazyDict' object already has attribute 'foo' Changing the line if hasattr(self, attr): to if hasattr(super(LazyDict, self), attr): fixes this as it only checks for proper dictionary attributes, allowing you to override the ones you're making: >>> lazy = LazyDict() >>> lazy.foo = 'bar' >>> lazy.foo = 'baz' >>> lazy.foo 'baz'Putting the __getattr__ logic inside a "try, except KeyError" is another small improvement, depending on your likes and dislikes of course :)
Thanks for the suggestion Floes, I updated the post.