[Python-Dev] Possible undefined behavior on creating a method named "__dict__"

Brett Cannon brett at python.org
Wed Apr 11 13:46:00 EDT 2018


On Wed, 11 Apr 2018 at 05:09 Steven D'Aprano <steve at pearwood.info> wrote:

> On Wed, Apr 11, 2018 at 08:21:01AM -0300, Joao S. O. Bueno wrote:
> > I just came across a code snippet that
> > would define a method with the "__dict__" name  - like in:
> >
> > class A:
> >     def __dict__(self):
> >          return ()
>
> That's a strange thing to do, but I don't think it ought to be illegal.
> Consenting adults and all that.
>
>
> > The resulting class's instances can be assigned
> > dynamic attributes as usual, but one can never acess
> > its actual local variables through instance.__dict__ -
> > the method is retrieved instead.
>
> Yes, I believe that is expected behaviour for attribute access since the
> descriptor protocol was added. Methods take priority over data
> attributes, if I recall correctly.
>

Yep, they do.


>
>
> > Calling "vars" will also fail on objects of this class.
>
> I consider that a pseudo-bug. I can't call it an actual bug, because
> vars() doesn't document that it will work even when __dict__ is shadowed
> in this way, but I think it should. So its a bug against a future
> feature :-)
>
> Attribute access still works correctly even with such a shadow:
>
> py> class W:
> ...     def __dict__(self):
> ...             return ()
> ...
> py> obj = W()
> py> obj.spam = 1
> py> obj.spam
> 1
>
> so there is still an instance dict somewhere inside the instance, and
> the C attribute-access machinary can access it. I think vars() should be
> able to do the same.
>
> (I'm not saying this in order to encourage people to shadow __dict__.)
>
>
> > This behavior is weird, and I believe is actually a side-effect
> > of implementation details on CPython.
>
> Its certain a weird thing to do, but I don't believe it is an
> implementation detail. Apart from the behaviour of vars(), I think the
> behaviour here all follows from the documented behaviour of the
> descriptor protocol.
>
>
> > I am not sure whether it should just:
> > 1 - be left as is - whoever reuses __dict__ as a method had it coming
> > 2 - document  CPython behavior
> > 3 - file that as a bug to disallow __dict__ override in class declaration
> > 4 - file that as a bug to not-create class __dict__ when one is explictly
> >       created in Python code (the same that happens when one have
> "__slots__".
> >
> > I have the feeling that (1) is just good - but then, I am at least
> > posting this e-mail here.
>
> I agree that (1) is the best, but vars() ought to work even in the
> presence of a method shadowing __dict__.
>

I say option 1 as well.

-Brett


>
>
> > Similar weird things go when one creates a method named "__class__",
> > and possible other names.
>
> type(instance) still works correctly when instance.__class__ is shadowed
> by a method.
>
>
> --
> Steve
> _______________________________________________
> Python-Dev mailing list
> Python-Dev at python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> https://mail.python.org/mailman/options/python-dev/brett%40python.org
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20180411/8c1e9051/attachment.html>


More information about the Python-Dev mailing list