Python 2.2, creating new types from base types

Milliken, Peter Peter.Milliken at GTECH.COM
Fri Jan 18 02:57:55 EST 2002


Hi Jason,

Thanks for the suggestion(s) and information. I'll give it a go. I didn't
realise the (naturally) recursive nature of how x['a']['b']['c'] would be
interpreted and executed - it makes sense :-)

Others have suggested the UserDict approach (which I wasn't aware of - I
guess I read it at some stage and then dismissed it in the initial
information gathering when I was learning Python).

I'll give your approach a try. My news group server may or may not be down
(I am dialed in from home) so this reply may not get there, but email seems
to be working so the reply should get to your email address at least :-)

Thanks again,
Peter  

-----Original Message-----
From: Jason Orendorff [mailto:jason at jorendorff.com]
Sent: Friday, January 18, 2002 5:37 PM
To: python-list
Cc: peter.milliken at gtech.com
Subject: Python 2.2, creating new types from base types


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