How to use type hints in python 3.6?
I noticed Python 3.5 and Python 3.6 added a lot of features about static type checking, so I tried with the following code (in python 3.6, stable version).
from typing import List
a: List[str] = []
a.append('a')
a.append(1)
print(a)
What surprised me was that, Python didn't give me an error or warning, although 1
was appended to a list
which should only contain strings. Pycharm
detected the type error and gave me a warning about it, but it was not obvious and it was not shown in the output console, I was afraid sometimes I might miss it. I would like the following effects:
- If it's obvious that I used the wrong type just as shown above, throw out a warning or error.
- If the compiler couldn't reliably check if the type I used was right or wrong, ignore it.
Is that possible? Maybe mypy
could do it, but I'd prefer to use Python-3.6-style type checking (like a: List[str]
) instead of the comment-style (like # type List[str]
) used in mypy
. And I'm curious if there's a switch in native python 3.6 to achieve the two points I said above.
Solution 1:
Type hints are entirely meant to be ignored by the Python runtime, and are checked only by 3rd party tools like mypy and Pycharm's integrated checker. There are also a variety of lesser known 3rd party tools that do typechecking at either compile time or runtime using type annotations, but most people use mypy or Pycharm's integrated checker AFAIK.
In fact, I actually doubt that typechecking will ever be integrated into Python proper in the foreseable future -- see the 'non-goals' section of PEP 484 (which introduced type annotations) and PEP 526 (which introduced variable annotations), as well as Guido's comments here.
I'd personally be happy with type checking being more strongly integrated with Python, but it doesn't seem the Python community at large is ready or willing for such a change.
The latest version of mypy should understand both the Python 3.6 variable annotation syntax and the comment-style syntax. In fact, variable annotations were basically Guido's idea in the first place (Guido is currently a part of the mypy team) -- basically, support for type annotations in mypy and in Python was developed pretty much simultaneously.
Solution 2:
Is that possible? Maybe mypy could do it, but I'd prefer to use Python-3.6-style type checking (like
a: List[str]
) instead of the comment-style (like# type: List[str]
) used in mypy. And I'm curious if there's a switch in native python 3.6 to achieve the two points I said above.
There's no way Python will do this for you; you can use mypy
to get type checking (and PyCharms built-in checker should do it too). In addition to that, mypy
also doesn't restrict you to only type comments # type List[str]
, you can use variable annotations as you do in Python 3.6 so a: List[str]
works equally well.
With mypy
as is, because the release is fresh, you'll need to install typed_ast
and execute mypy
with --fast-parser
and --python-version 3.6
as documented in mypy's docs. This will probably change soon but for now you'll need them to get it running smoothly
Update: --fast-parser
and --python-version 3.6
aren't needed now.
After you do that, mypy detects the incompatibility of the second operation on your a: List[str]
just fine. Let's say your file is called tp_check.py
with statements:
from typing import List
a: List[str] = []
a.append('a')
a.append(1)
print(a)
Running mypy
with the aforementioned arguments (you must first pip install -U typed_ast
):
python -m mypy --fast-parser --python-version 3.6 tp_check.py
catches the error:
tp_check.py:5: error: Argument 1 to "append" of "list" has incompatible type "int"; expected "str"
As noted in many other answers on type hinting with Python, mypy
and PyCharm
s' type-checkers are the ones performing the validation, not Python itself. Python doesn't use this information currently, it only stores it as metadata and ignores it during execution.
Solution 3:
Type annotations in Python are not meant to be type-enforcing. Anything involving runtime static-type dependency would mean changes so fundamental that it would not even make sense to continue call the resulting language "Python".
Notice that the dynamic nature of Python does ALLOW for one to build an external tool, using pure-python code, to perform runtime type checking. It would make the program run (very) slowly, but maybe it is suitable for certain test categories.
To be sure - one of the fundamentals of the Python language is that everything is an object, and that you can try to perform any action on an object at runtime. If the object fails to have an interface that conforms with the attempted operation, it will fail - at runtime.
Languages that are by nature statically typed work in a different way: operations simply have to be available on objects when tried at run time. At the compile step, the compiler creates the spaces and slots for the appropriate objects all over the place - and, on non-conforming typing, breaks the compilation.
Python's typechecking allows any number of tools to do exactly that: to break and warn at a step prior to actually running the application (but independent from the compiling itself). But the nature of the language can't be changed to actually require the objects to comply in runtime - and veryfying the typing and breaking at the compile step itself would be artificial.
Although, one can expect that future versions of Python may incoroporate compile-time typechecking on the Python runtime itself - most likely through and optional command line switch. (I don't think it will ever be default - at least not to break the build - maybe it can be made default for emitting warnings)
So, Python does not require static type-checking at runtime because it would cease being Python. But at least one language exists that makes use both of dynamic objects and static typing - the Cython language, that in practice works as a Python superset. One should expect Cython to incorporate the new type-hinting syntax to be actual type-declaring very soon. (Currently it uses a differing syntax for the optional statically typed variables)