Python dict using dot notation and chaining
Question: Ideally what I am aiming to accomplish is a class that extends (or is very
similar to) a `dict` in Python with the additional capabilities:

  * Dot-Notation capable for setting and getting values
  * Key-Value capabilities like `dict` (i.e. setitem,getitem)
  * Can chain dot-notated operations

The goal is if I have something like `example = DotDict()` I could do the
following against it `example.configuration.first= 'first'` and it would
instantiate the appropriate DotDict instances under `example` with the really
painful caveat being that if the operation is not assignment it should simply
raise a `KeyError` like a `dict` would do

Here is what I have naively assembled

    
    
    class DotDict(dict):
        def __getattr__(self, key):
            """ Make attempts to lookup by nonexistent attributes also attempt key lookups. """
            import traceback
            import re
            s= ''.join(traceback.format_stack(sys._getframe(1),1))
            if re.match(r'  File.*\n.*[a-zA-Z]+\w*\.[a-zA-Z]+[a-zA-Z0-9_. ]*\s*=\s*[a-zA-Z0-9_.\'"]+',s):
                self[key] = DotDict()
                return self[key]
    
            return self[key]
    
        def __setattr__(self, key, value):
            if isinstance(value,dict):
                self[key] = DotDict(value)
            self[key] = value
    

It works except for some common edge cases, I must say that I absolutely hate
this method and there must be a better way. Looking at the stack and running a
regular expression on the last line is not a good way to accomplish this.

The heart of the matter is that Python interprets lines of code left to right
so when it arrives at a statement like `a.b.c = 3` it's first operation is a
`getattr(a,b)` and not a `setattr` so I can't determine easily if the last
operation in the stack of operations is an assignment.

What I would like to know is if there is a good way to determine the last
operation in the stack of operations or at least if it's a `setattr`.

Edit:

This is the solution that I came up with thanks to user1320237's
recommendation.

    
    
    class DotDict(dict):
        def __getattr__(self, key):
            """ Make attempts to lookup by nonexistent attributes also attempt key lookups. """
            if self.has_key(key):
                return self[key]
            import sys
            import dis
            frame = sys._getframe(1)
            if '\x00%c' % dis.opmap['STORE_ATTR'] in frame.f_code.co_code:
                self[key] = DotDict()
                return self[key]
    
            raise AttributeError('Problem here')
    
        def __setattr__(self, key, value):
            if isinstance(value,dict):
                self[key] = DotDict(value)
            self[key] = value
    

There's a little bit more in the actual implementation but it does an awesome
job. The way it works is that it inspects the last frame in the stack and
checks the byte code for a STORE_ATTR operation which means that the operation
being performed is of the `a.b.this.doesnt.exist.yet = 'something'`
persuasion. I would be curious if this could be done on other interpreters
outside of CPython.


Answer: You may need to overwrite **getattribute** for those edge cases and then use
the

    
    
    object.__getattribute__
    

Have a look at the module [dis](http://docs.python.org/library/dis.html). But
what you wrote is nicer than disassembling.

    
    
    >>> import dis
    >>> def g():
        a.b.c = 4
    
    
    >>> dis.dis(g)
      2           0 LOAD_CONST               1 (4)
                  3 LOAD_GLOBAL              0 (a)
                  6 LOAD_ATTR                1 (b)
                  9 STORE_ATTR               2 (c)
                 12 LOAD_CONST               0 (None)
                 15 RETURN_VALUE        
    

