Using the variable type annotation as a placeholder in a nonlocal scope?

594 Views Asked by At

Since PEP 526 -- Syntax for Variable Annotations was approved, in Python 3.6+ it is possible to provide type hint information in the form x: int, also the PEP says "However, annotating a local variable will cause the interpreter to always make it local to the scope and leaves the variable uninitialized". Therefore in Python 3.6+ it is syntactically legal to write:

def outer():
    x: int
    def inner():
        nonlocal x
        x = 10
    inner()
    print(x)

while the above snippet is semantically more equivalent to:

def outer():
    #x 
    def inner():
        nonlocal x
        x = 10
    inner()
    print(x)

Which is obviously a SyntaxError: no binding for nonlocal 'x' found, sorry for the pun. Also there is nothing said about this style in PEP 8 and Python 3.6 docs.

So should I consider this as a bug, or an implementation detail (side effect), or a wart, or a feature?

After some googling on the web, I found that this effect is already used in stdlib - typing.NamedTuple but actually class bodies are not scopes and also this effect seems to be exploited in Python 3.7 @dataclasses. This situation really surprises me, it turns out that some things can not be done without type annotations, while their only intention was to provide type hints without any run-time or compile-time effects.

Relatively nonlocal part, this question is pretty close to:

  1. When existence of nonlocal variables is checked?
  2. Accessing variables defined in enclosing scope

and from this perspective it can be closed. In fact we can not come to a consensus and I would like to hear your thoughts of possible pitfalls, if any, if we choose to use this form in our codebase.

0

There are 0 best solutions below