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 
the 
> 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 
my 
> __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 
accessors.

-- 
Duncan Booth http://kupuguy.blogspot.com



More information about the Python-list mailing list