Steven D'Aprano <st...@remove-this-cybersource.com.au> wrote: > On Mon, 20 Sep 2010 11:53:48 +0000, Duncan Booth wrote: > >> 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. > > Yes, I already override items(), keys(), values(), their iter... > versions, and just about every damn method that dicts have :/ > > I suspect that the dict() constructor is just grabbing the key/value > pairs directly from the underlying hash table. If that's the case, my > choices are to not inherit from dict at all, or take your suggestion and > keep an auxiliary dict alongside the main one. > >From Python 2.x sources that I have lying around (sorry I have no idea if the code for 3.x has changed much):
dict_init calls dict_update_common which does: if (PyObject_HasAttrString(arg, "keys")) result = PyDict_Merge(self, arg, 1); else result = PyDict_MergeFromSeq2(self, arg, 1); PyDict_Merge says: /* We accept for the argument either a concrete dictionary object, * or an abstract "mapping" object. For the former, we can do * things quite efficiently. For the latter, we only require that * PyMapping_Keys() and PyObject_GetItem() be supported. */ which basically boils down to "if PyDict_Check() is true then iterate directly over the structure and use the existing key, hash and value fields to insert into the new dict". If PyDict_Check() is false then it iterates over the keys and calls PyObject_GetItem(). -- Duncan Booth http://kupuguy.blogspot.com -- http://mail.python.org/mailman/listinfo/python-list