Python 2.2, creating new types from base types

Jason Orendorff jason at jorendorff.com
Fri Jan 18 01:37:04 EST 2002


Peter,

> It seems like it should work, but doesn't..... Certainly being
> able to subclass dict to come up with a specialised form of
> dict should be achievable using the new features.

I don't think you need to subclass dict here.  You might be
more comfortable with the semantics of UserDict.

When you write x['a']['b']['c'], Python basically does
x.__getitem__('a').__getitem__('b').__getitem__('c') .

If you want to attach special behavior to only the 2nd
__getitem__ call, you need to make sure that the first
__getitem__ call returns an object that has that
special behavior.

Here's my stab at it.  You'll want to modify my __getitem__()
method where it says "elif self.depth == 2: ..."

## Jason Orendorff    http://www.jorendorff.com/



from UserDict import UserDict

class MyDict(UserDict):
    def __init__(self, data=None, depth=3):
        UserDict.__init__(self)
        self.depth = depth
        if data is not None:
            if not hasattr(data, 'iteritems'):
                # Convert data to a dict first.
                data = dict(data)
            self.update(data)

    def __getitem__(self, key):
        """ Get a sub-dictionary.  Sneakily create one if none yet exists
        for the given key.
        """
        try:
            return self.data[key]
        except KeyError:
            if self.depth > 2:
                x = self.data[key] = MyDict(depth=self.depth - 1)
            elif self.depth == 2:
                x = self.data[key] = {}
            else:
                raise
            return x

    def update(self, other):
        for k, v in other.iteritems():
            self[k].update(v)


>>> from MyDict import MyDict
>>> m = MyDict({'a' : {'b': {'c': 14434, 'd': 66341}}})
>>> m
{'a': {'b': {'c': 14434, 'd': 66341}}}
>>> m['a']['b']['c']
14434
>>> m['d']['e']['f'] = 95832
>>> m
{'a': {'b': {'c': 14434, 'd': 66341}}, 'd': {'e': {'f': 95832}}}
>>> m['d'].__class__
<class udict.MyDict at 0x00A4FD00>





More information about the Python-list mailing list