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

Random832 random832 at fastmail.com
Fri Apr 22 00:45:34 EDT 2016



On Thu, Apr 21, 2016, at 23:49, Steven D'Aprano wrote:
> "Items"? Like items in a dict? Then you already have at least two ways: 
> you override __getitem__, or add a __missing__ method to the dict.
> 
> What makes you think these techniques don't work?

The fact that I tried them and they didn't work.

> Where does attribute lookup come into this?

Because looking up an attribute implies getting an item from the object
or class's __dict__ with a string key of the name of the attribute (see
below for the documented basis for this assumption). How are you not
following this? I don't believe you're not messing with me. 

> Classes and instances may not have a __dict__ at all, if they define 
> __slots__ instead, or if they are builtins:

If a class defines __slots__, the *instances* don't have a __dict__, but
the *class* sure as hell still does. Even, as it turns out, if the
metaclass had __slots__. (Not sure what's up with that, actually).

> What makes you think that such a method exists?
> 
> Have you read the rest of this thread? If not, I suggest you do, because 
> the thread is all about making unjustified assumptions about how objects 
> are implemented. You are doing it again. Where is it documented that 
> there is a method on the object __dict__ (if such a __dict__ even 
> exists!) that does this?

My main concern here is the class dict. So, let's see...

### Class attribute references are translated to lookups in this
dictionary, e.g., C.x is translated to C.__dict__["x"]

Now, that is technically true (C.__dict__ is, we've established, not the
actual dict, but a "mappingproxy" object), but this behavior itself
contradicts the documentation:

### [type] With three arguments, [...] and the dict dictionary is the
namespace containing definitions for class body and becomes the __dict__
attribute.

Except, it *doesn't* become the __dict__ attribute - its contents are
*copied* into the __dict__ object, which is a new "mappingproxy" whose
contents will not reflect further updates to the dict that was passed
in.

And regarding the object __dict__, when such a __dict__ *does* exist
(since, unlike class dicts, you actually can set object dicts to be
arbitrary dict subclasses)

### The default behavior for attribute access is to get, set, or delete
the attribute from an object’s dictionary. For instance, a.x has a
lookup chain starting with a.__dict__['x'], then type(a).__dict__['x'],
and continuing through the base classes of type(a) excluding
metaclasses.

> > Given a type, how do I get a reference to the dict instance that was
> > passed to the type's constructor?
> 
> I believe that the answer to that is, you can't.

I hadn't yet realized, when I asked this question, that the class
__dict__ "mappingproxy" is a new object (that isn't even a dict! "A
class has a namespace implemented by a dictionary object" was also
wrong) and doesn't retain a reference to the passed-in dict nor reflect
changes to it.


More information about the Python-ideas mailing list