[Python-ideas] Delay evaluation of annotations

אלעזר elazarg at gmail.com
Thu Sep 22 15:21:18 EDT 2016


On Thu, Sep 22, 2016 at 9:43 PM Steven D'Aprano <steve at pearwood.info> wrote:

> On Thu, Sep 22, 2016 at 05:19:12PM +0000, אלעזר wrote:
> > Hi all,
> >
> > Annotations of function parameters and variables are evaluated when
> > encountered.
>
> Right, like all other Python expressions in general, and specifically
> like function parameter default arguments.
>

Just because you call it "expression", when for most purposes it isn't - it
is an annotation. "Expression" is something that you need its value right
now, and "annotation" is something that, well, annotates the code you see
right now. Terminology is not the important thing, but that seems to be the
basis your argument here.

> This makes it necessary to use string representation for names
> > that are not yet bound, which affects almost every class definition.
>
> Almost every class? Really? I find that implausible. Still, I can see it
> affecting *many* class definitions, so let's not quibble.
>
> I retract this as a factual claim, I think we agree here.


> It is
> > also easy to forget, and the result might be a (very uninteresting)
> > exception in certain untested paths, e.g. inside functions.
>
> Unlikely, unless you're talking about functions nested inside other
> functions, or unusual (but legal and sometimes useful) conditional
> definitions:
>
I was thinking about the former, but yeah, uncovered code will fail at
runtime, possibly in production, for *no* real reason. I do not claim that
this is common, but it is definitely unnecessary - unlike initialization
expressions.

(which I would have liked to see delayed too, but I can understand the
reasons why this is strongly opposed; it *is* an expression. Sadly bugs are
*much* more common there).


> if condition:
>     # forward reference to MyClass
>     def f(arg:'MyClass'): ...
> else:
>     # oops, untested path
>     def f(arg:MyClass): ...
>
> class MyClass: ...
>
>
> But generally speaking, that sort of code is unusual, and besides, if
> you're doing this, either the static type checker won't be able to cope
> with it at all (in which case there's little point in annotating the
> function), or it will cope, and detect the invalid annotation.
>
> Why would it detect invalid annotation here? It shouldn't.

And of course the fact that I use annotated code does not necessarily mean
I also use type checkers.


> > Editors and
> > IDEs also don't handle it well; for example, PyDev does not consider
> > string-annotations as an occurrence of the name, and warns about unused
> > imports.
>
> I would call that a bug in PyDev.
>
> Agreed - given the current situation, which calls for bugs in IDEs and
requires unnecessary effort from any person or tool parsing the code.


> > I propose delaying evaluation of annotation-expressions by either keeping
> > the AST of the annotation, or turning it implicitly from EXP into
> "lambda:
> > EXP". Inspection code that is interested in this information can access
> it
> > be calling (or evaluating) it.
>
> -1 on complicating the simple Python model that expressions are
> evaluated when they are reached.
>
> Again, should not be called "expressions" but "annotations", and every
reader that understand types will not expect it to be evaluated. So the
current "simple" model is actually surprising. It's only easier on the
implementation side.

You would also complicate the introspection of annotations. With
> your proposal, *every* annotation would be a function, and every(?)
> inspection would require calling the function to find out what the real
> annotation is.
>

This argument was partially answered by Alexander before. Generally,
introspection *libraries* will be tiny bit more complicated. Introspection
user code will not. And people that write introspection code *must*
understand the nitty-gritty details of the language, whereas people that
read and write regular code need not.


> And what would that do to modules which use annotations for some other
> purpose? I know Guido is keen to discourage such alternative uses, but
> they're still legal, and a change like this would outright break them.
>

I don't know any concrete examples. Can you give any? Are these examples
use side effects on annotation evaluation? Lastly, do *you* consider it a
good idea, one that should be accounted for?


> Personally, I'm not convinced that it is a burden to expect people to
> remember to quote forward references. If they forget, they will nearly
> always get a NameError at runtime or a warning/error when they run the
> type checker.
>

It's just another irritating inconvenience making the write-test cycle
longer for no obvious reason (at least from the perspective of the user).

> It certainly isn't a backward compatible change, but I think it won't
> > affect too much code. On the positive side, it will make annotated code
> > much more pleasing to read,
>
> A bit more pleasant. It's not unpleasant to read 'MyClass' instead of
> MyClass.
>

It is to me, but that's only personal taste.


> > will be less surprising for beginners,
>
> Only because said beginners aren't familar enough to be surprised by how
> surprising this is.
>

I don't understand this answer at all. I am pretty familiar with Python -
not as most of the people on this list, but possibly not less than anyone I
know in person (sadly so). And this behavior still surprises me. It
definitely surprises people coming from a statically-typed background.


> > and will
> > help editors in syntax highlighting and name lookup.
>
> But will harm runtime introspection.
>

Very little. And to quote Frank Miller, “An old man dies, a little girl
lives. Fair trade.”

Elazar
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20160922/a9e46e90/attachment-0001.html>


More information about the Python-ideas mailing list