Hm. It's unfortunate that this would break code using what is *currently*
the best practice.

The saving grace seems that for *many* use cases the best practice is to
call typing.get_type_hints(). This is particularly useful for classes
because it includes annotations from base classes.

Also, for functions and modules I would recommend `getattr(o,
"__annotations__", None)` (perhaps with `or {}` added).

I would also honestly discount what dataclasses.py and typing.py have to
do. But what do 3rd party packages do when they don't want to use
get_type_hints() and they want to get it right for classes? That would give
an indication of how serious we should take breaking current best practice.

On Mon, Jan 18, 2021 at 1:10 PM Larry Hastings <la...@hastings.org> wrote:

>
> On 1/18/21 12:16 PM, Guido van Rossum wrote:
>
> I do worry about the best practice getting worse if your PEP 649 is
> accepted.
>
>
> A good part of what motivated me to start this second thread ("Let's Fix
> ...") was how much worse best practice would become if PEP 649 is
> accepted.  But if we accept PEP 649, *and* take steps to fix the
> semantics of annotations, I think the resulting best practice will be
> excellent in the long-run.
>
> Let's assume for a minute that PEP 649 is accepted more-or-less like it is
> now.  (The name resolution approach is clearly going to change but that
> won't affect the discussion here.)  And let's assume that we also change
> the semantics so annotations are always defined (you can't delete them) and
> they're guaranteed to be either a dict or None.  (Permitting
> __annotations__ to be None isn't settled yet, but it's most similar to
> current semantics, so let's just assume it for now.)
>
> Because the current semantics are kind of a mess, most people who examine
> annotations already have a function that gets the annotations for them.
> Given that, I really do think the best approach is to gate the code on
> version 3.10, like I've described before:
>
> if python version >= 3.10:
>     def get_annotations(o):
>         return o.__annotations__
> else:
>     def get_annotations(o):
>         if isinstance(o, (type, types.ModuleType)):
>             return o.__dict__.get("__annotations__", None)
>         else:
>             return o.__annotations__
>
> This assumes returning None is fine.  If it had to always return a valid
> dict, I'd add "or {}" to the end of every return statement.
>
> Given that it already has to be a function, I think this approach is
> readable and performant.  And, at some future time when the code can drop
> support for Python < 3.10, we can throw away the if statement and the whole
> else block, keeping just the one-line function.  At which point maybe we'd
> refactor away the function and just use "o.__annotations__" everywhere.
>
>
> I concede that, in the short term, now we've got nine lines and two if
> statements to do something that *should* be relatively
> straightforward--accessing the annotations on an object.  But that's where
> we find ourselves.  Current best practice is kind of a mess, and
> unfortunately PEP 649 breaks current best practice anyway.  My goal is to
> fix the semantics so that long-term best practice is sensible, easy, and
> obvious.
>
>
> Cheers,
>
>
> */arry*
>


-- 
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*
<http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
_______________________________________________
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/Y7KUIKUHFQJ564HM2JNFFZF5EJHLNR2P/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to