[Python-Dev] Possible undefined behavior on creating a method named "__dict__"
Steven D'Aprano
steve at pearwood.info
Wed Apr 11 08:08:06 EDT 2018
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.
> 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 shoud just:
> 1 - be left as is - whoever reuses __dict__ as a method had it coming
> 2 - document CPythn 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
precence of a method shadowing __dict__.
> 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
More information about the Python-Dev
mailing list