(original) (raw)



On Wed, 11 Apr 2018 at 05:09 Steven D'Aprano <steve@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@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: https://mail.python.org/mailman/options/python-dev/brett%40python.org