Overriding dict constructor

Duncan Booth duncan.booth at invalid.invalid
Mon Sep 20 13:53:48 CEST 2010

Steven D'Aprano <steve at REMOVE-THIS-cybersource.com.au> wrote:

> I have a dict subclass that associates extra data with each value of 
> key/value items:
> class MyDict(dict):
>     def __setitem__(self, key, value):
>         super(MyDict, self).__setitem__(key, (value, "extra_data"))
>     def __getitem__(self, key):
>         return super(MyDict, self).__getitem__(key)[0]
>     # plus extra methods
> This works fine for item access, updates, etc:
>>>> d = MyDict()
>>>> d[0] = 'a'; d[1] = 'b'
>>>> d[1]
> 'b'
> But if I try to create a regular dict from this, dict() doesn't call 
> __getitem__ method:
>>>> dict(d)
> {0: ('a', 'extra_data'), 1: ('b', 'extra_data')}
> instead of {0: 'a', 1: 'b'} as I expected.
> How can I fix this?

I was going to suggest overriding items() (or iteritems() for Python 
2.x), but while that is another hole that your values leak out it isn't 
the hole used by the dict constructor.

It might be simpler to duck the issue entirely and store the extra data 
in another dict alongside the main one:

class MyDict(dict):
    def __init__(self, *args, **kw):
	self._extra = {}
	super(MyDict, self).__init__(*args, **kw)
	for k in self:
	    self._extra[k] = "extra_data"

    def __setitem__(self, key, value):
        super(MyDict, self).__setitem__(key, value)
        self._extra[key] = "extra_data"
    # plus extra methods

then you only have to worry about catching all the mutators but not the 

Duncan Booth http://kupuguy.blogspot.com

More information about the Python-list mailing list