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