[Python-ideas] Override dict.__new__ to raise if cls is not dict; do the same for str, list, etc.

Random832 random832 at fastmail.com
Thu Apr 21 22:35:01 EDT 2016


On Thu, Apr 21, 2016, at 22:00, Steven D'Aprano wrote:
> I don't understand your question. Or rather, if I have understood it, 
> the question has a trivial answer: you don't have to override anything.

I thought it went without saying that I want to be able to get items
other than by having them already stored in the dict under the exact
key. Like if I wanted to make a case-insensitive dict, or one where
numbers are equivalent to strings, or have it materialize a default
value for missing keys.

> "So what method should be overridden..."
> 
> but the answer to this in general must be "What makes you think a single 
> method is sufficient?"

Well, I was assuming it doesn't call *more than one* method for the
specific task of looking up an attribute by name, even if there are
other methods for other tasks that I would have to override to get the
whole package of what behavior I want. As near as I can tell, it doesn't
call *any method at all*, but instead reaches inside PyDictObject's
internal structure.

> This doesn't just apply to dicts, it applies in 
> general to any class.
> 
> "What method do I override to make a subclass of int implement 
> arithmetic with wrap-around (e.g. 999+1 = 0, 501*2 = 2)?"

Right, but I'm asking which method *one particular* expression calls.
This is more like "Which method on an object implements the + operator",
only it's "Which method on an object's type's namespace dict implements
the ability to look up attributes on that object?"

In code terms:

class mydict(dict):
    def ????????(self, name):
        if name == 'foo': return 'bar'

mytype = type('C',(),mydict())

=> desired result: mytype().foo == mytype.foo == 1

> > I can't even figure out how to get the real class dict, as I would need
> > if I were overriding __getattribute__ explicitly in the metaclass (which
> > also doesn't work) - cls.__dict__ returns a mappingproxy.
> 
> This doesn't make anything any clearer for me.

Given a type, how do I get a reference to the dict instance that was
passed to the type's constructor?

Or, in code terms:

>>> mydict = {}
>>> mytype = type('C',(),mydict)
>>> mytype.__dict__ is mydict
False
>>> type(mytype.__dict__)
<class 'mappingproxy'>

def f(x): ???????? => desired result: f(mytype) is mydict

> > Alternatively, where, other than object and class dicts, are you
> > actually required to have a subclass of dict rather than a UserDict or
> > other duck-typed mapping?
> 
> Anywhere you have to operate with code that does "if isinstance(x, 
> dict)" checks.

Fix the other code, because it's wrong. If you can't, monkey-patch its
builtins.

> > Incidentally, why is __missing__ documented under defaultdict as "in
> > addition to the standard dict operations"?
> 
> Because defaultdict provides __missing__ in addition to the standard 
> dict operations. Is there a problem with the current docs?

When I read it earlier, the wording in defaultdict's documentation
seemed to suggest that what it provides is the ability to define a
__missing__ method and have it be called - and that, itself, *is* a
"standard dict operation" - rather than an implementation of the method.
It looks like I misinterpreted it though.


More information about the Python-ideas mailing list