[Python-ideas] Delay evaluation of annotations

Steven D'Aprano steve at pearwood.info
Thu Sep 22 14:42:16 EDT 2016


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


More information about the Python-ideas mailing list