[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