[Python-Dev] Creating dicts from dict subclasses

Walter Dörwald walter at livinglogic.de
Wed Dec 13 23:18:53 CET 2006


Guido van Rossum wrote:
> On 12/13/06, Walter Dörwald <walter at livinglogic.de> wrote:
>> I tried to reimplement weakref.WeakValueDictionary as a subclass of
>> dict. The test passes except for one problem: To compare results
>> test_weakref.py converts a weakdict to a real dict via dict(weakdict).
>> This no longer works because PyDict_Merge() does a PyDict_Check() on the
>> argument and then ignores all overwritten methods. (The old version
>> worked because UserDict.UserDict was used).
>>
>> The simplest solution is to replace the PyDict_Check() call with
>> PyDict_CheckExact(), but this might slow things down too much, because
>> the fallback code basically does:
>>
>>    for key in iter(arg.keys()):
>>       self[key] = arg.__getitem__(key)
>>
>> Why can't we use:
>>
>>    for key in iter(arg):
>>       self[key] = arg.__getitem__(key)
>>
>> instead?
> 
> The only reason I can think of is backwards compatibility: not all
> "mappings" created pre-2.2 would support iteration. Maybe you could
> check for a tp_iter slot and if non-NULL use the latter otherwise use
> the original fallback?

This doesn't seem to work. It breaks test_update() in test_dict.py which
does this:

    d = {}
    class SimpleUserDict:
        def __init__(self):
            self.d = {1:1, 2:2, 3:3}
        def keys(self):
            return self.d.keys()
        def __getitem__(self, i):
            return self.d[i]
    d.update(SimpleUserDict())
    self.assertEqual(d, {1:1, 2:2, 3:3})

This fails with

    KeyError: 0

because SimpleUserDict doesn't implement __iter__, so it gets an
iterator implementation via __getitem__.

So maybe this only makes sense for Python 3.0 where we can demand that
dict-like classes implement __iter__?

Servus,
   Walter



More information about the Python-Dev mailing list