On Mon, Jan 11, 2021 at 9:23 AM Larry Hastings <la...@hastings.org> wrote:

> [SNIP - background info]
>
>
> If I could wave my magic wand and do whatever I wanted, I'd change the
> semantics for __annotations__ to the following:
>
> * Functions, classes, and modules always have an __annotations__ member
> set.
> * "del o.__annotations__" always throws a TypeError.
> * The language will set __annotations__ to a dict if the object has
>   annotations, or None if it has no annotations.
> * You may set __annotations__, but you can only set it to either None or a
>   dict (passes PyDict_Check).
> * You may only access __annotations__ as an attribute, and because it's
>   always set, best practice is to use "o.__annotations__" (though getattr
>   will always work too).
> * How __annotations__ is stored is implementation-specific behavior;
>   looking in the relevant __dict__ is unsupported.
>
> This would grant sanity and consistency to __annotations__ in a way it's
> never so far enjoyed.  The problem is, it's a breaking change.  But the
> existing semantics are kind of terrible, so at this point my goal is to
> break them. I think the best practice needs to stop requiring examining
> cls.__dict__; in fact I'd prefer people stop doing it altogether.
>

So the biggest potential breakages are code that:

   1. Directly get the attribute from __dict__
   2. The fact that it would no longer be inherited

Am I missing anything else?

For issue #1, it seems that inspect.get_type_hints(), as you point out
below, resolves that. As well, code could be updated appropriately without
much effort to check different places if the attribute was not found in
__dict__.

For issue #2, if the default was `None`, then couldn't that be used as an
implicit feature marker that you can't (incorrectly) rely on inheritance to
percolate up the annotations of the superclass if the subclass happens to
not define any annotations?

This all seems reasonable to me. Since it's a change to the object model it
will probably need a PEP, but I would suspect it would mostly revolve
around guiding people to how to update their code to work across Python
versions.

-Brett

>
> If we change the behavior as part of a new release of Python,
> code that examines annotations on classes can do a version check:
>
>     if (sys.version_info.major >=3
>         and sys.version_info.minor >= 10):
>
>         def get_annotations(o):
>             return o.__annotations__ or {}
>     else:
>         def get_annotations(o):
>             # eight or ten lines of complex code goes here
>             ...
>
> Or code can just use inspect.get_type_hints(), which is tied to the Python
> version
> anyway and should always do the right thing.
>
>
> */arry*
> _______________________________________________
> Python-Dev mailing list -- python-dev@python.org
> To unsubscribe send an email to python-dev-le...@python.org
> https://mail.python.org/mailman3/lists/python-dev.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-dev@python.org/message/AWKVI3NRCHKPIDPCJYGVLW4HBYTEOQYL/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/IY55VJHCYD2P3ZJUJI4RXX6UZS3I2LB5/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to