[Python-ideas] Delay evaluation of annotations

Stephen J. Turnbull turnbull.stephen.fw at u.tsukuba.ac.jp
Sun Sep 25 13:42:18 EDT 2016


Nick Coghlan writes:

 > This code works as a doctest today:
 > 
 >     >>> def func(a: "Expected output"):
 >     ...     pass
 >     ...
 >     >>> print(func.__annotations__["a"])
 >     Expected output
 > 
 > Any change that breaks that currently valid doctest is necessarily a
 > compatibility break for the way annotations are handled at runtime. It
 > doesn't matter for that determination how small the change to fix the
 > second command is, it only matters that it *would* have to change in
 > some way.

This is a bit unfair to אלעזר, although it's been a long thread so I
can understand why some of his ideas have gone missing.  His proposals
have gotten a bit incoherent because he has been answering all the
different objections one by one rather than organizing things into a
single design, but I think eventually he would organize it as follows:

(1) Add __raw_annotations__ and save the thunked expressions there,
    whether as code objects or AST.
(2) Turn __annotations__ into a property which evaluates (and
    memoizes?) the thunks and returns them.  (First explicitly
    suggested by Alexander Belopol, I think.)

He claims that (2) solves the backward compatibility problem, I don't
have the knowledge to figure out whether it is that simple or not.  It
seems plausible to me, so I'd love to hear an explanation.  New ideas
like DBC would of course be supported by the new __raw_annotations__
since there's no backward compatibility issue there.

I'm still -1 on the whole thing on the principle "although sometimes
never is better than *right* now". I think the aClass = "aClass" trick
described by Chris is perfectly serviceable to deal with the PEP 484
forward type reference issue.  The "let's turn all the annotations
into expressions" idea can be practically exploited with ast.parse().
I'm guessing a decorator could be used to provide __raw_annotations__
and __annotations__ per (1) and (2) above (although I'm not sure how
to do it myself: copying __annotations__ to __raw_annotations__ and
then propertizing __annotations__ could be a bit tricky, I guess).



More information about the Python-ideas mailing list