dictionary question

Jason Orendorff jason at jorendorff.com
Wed Dec 5 13:51:45 EST 2001

=?gb2312?B?1cXJ2bPb?= <zhangsc at neusoft.com> wrote:
> Hello!
>   I have a question about python's dictionary,I have a dictionary 
> type variable, such as 
> dbs={'xk.dhs.org': '', 
> 'www.symantec.com':'', 'ftp.happynet.org':''}
> When I input dbs['www.symantec.com']='',I want to 
> get the result like that:
> dbs={'xk.dhs.org': '', 
> 'www.symantec.com':['',''],'ftp.happyn
> et.org':''}
> How to realize this function?

Python's built-in dictionary doesn't behave this way.  But you could
write your own dictionary that does this.

In particular, if you have Python 2.2b2 (the very latest), you can
just write a subclass of dict:

class multidict(dict):
    def __setitem__(self, key, value):
        if self.has_key(key):
            existing = self[key]
            if isinstance(existing, list):
                dict.__setitem__(self, key, [existing, value])
            dict.__setitem__(self, key, value)

This changes the behavior of __setitem__ in the way you want.
Try it out:

x = multidict()
x['alarmist.org'] = ''
x['jorendorff.com'] = ''
x['yahoo.com'] = ''
x['yahoo.com'] = ''
x['yahoo.com'] = ''
print x

> When I input dbs['www.symantec.com']='',how to 
> determine if this item has exists in dbs,if item has existed, the 
> result is still like this:  [...snip...]
> if item doesn't exist,then insert new value into dbs,How to 
> realize this function?

It's a minor tweak to the above code.  Instead of this...

you'll want to write this...
    if value not in existing:

> When I print dbs,I like the result as follows:  
> 'xk.dhs.org': ''
> 'www.symantec.com':''
> 'www.symantec.com':''
> 'ftp.happynet.org':''
>  How to realize these function?

Override __str__().  I suggest something like this...

class multidict(dict):

    ... same as above ...
    ... but add these methods ...

    def iteritems(self):
        for k, v in dict.iteritems(self):
            if isinstance(v, list):
                for item in v:
                    yield k, item
                yield k, v

    def items(self):
        return list(self.iteritems())

    def __str__(self):
        pieces = ["%r: %r" % item for item in self.iteritems()]
        data = ', '.join(pieces)
        return "{%s}" % data

To really flesh out the class, you'll eventually want to
override itervalues(), values(), popitem(), update(), and
maybe a few more.

If you're using an older version of Python, check out the UserDict

Jason Orendorff

More information about the Python-list mailing list