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/