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.
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.
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: 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.
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.
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. 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. 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. 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 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.
will be less surprising for beginners,
Only because said beginners aren't familar enough to be surprised by how surprising this is.
and will help editors in syntax highlighting and name lookup.
But will harm runtime introspection. -- Steve