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.
)
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.