missing "from typing import List" - error in script, but not in function

Viewed 313

I was recently surprised to see that some of our code had a linter warning on the "List" in something equivalent to:

class MyClass:
    def method(self):
        myVar: List[str] = []

The linter warning is because this file is missing from typing import List in the imports. So, PyCharm flags this as a linter error. Certainly the code is incorrect. What's surprising is this code runs, and has run properly for months!

Digging in, I found that this:

class MyClass:
    def method(self):
        myVar: List[str] = []

m = MyClass()
m.method()

And this:

def method(self):
    l: List[str] = []

method(None)

run properly, but this:

l: List[str] = []

Raises the expected error!

Traceback (most recent call last):
  File ".../scratches/scratch_3.py", line 5, in <module>
    l: List[str] = []
NameError: name 'List' is not defined

So... what gives?

(Versions: I am running

Python 3.7.1 (v3.7.1:260ec2c36a, Oct 20 2018, 14:57:15) [MSC v.1915 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>

But the code works on several different versions of PYTHON on WINDOWS and LINUX (UBUNTU) builds.
)

1 Answers

Python treats annotations for global & local variables differently, as outlined in PEP 526. Annotations for module- & class-level variables are evaluated, but annotations for local variables are not.

This makes some sense, as module- and class-level annotations can be accessed through the __annotations__ dictionary, so it must evaluate the annotation and record it. On the other hand, local variable annotations can not be programmatically accessed, so there's no point in evaluating them.

Related