Statyczne sprawdzanie typów po raz drugi
mypy
Kilka pojęć wstępnych
There are two independent characteristics that describe programming languages.
- When types are checked?
- How strictly types are checked?
When types are checked?
Statically typed languages check the types and look for type errors during compile time.
Dynamically typed languages check the types and look for type errors during runtime.
How strictly types are checked?
In a weakly typed language, the type of a value depends on how it is used.
In a strongly typed language, a value has a type and that type cannot change. What you can do to a value depends on the type of the value.
What is type hinting in python?
- Python is (and always will) very dynamically typed and rather strong. This means that variables can change types during execution, but each change has to be explicit. Python will not attempt to execute code ,,no matter what".
- One can annotate functions with type hints. It is treated as a comment by the intepreter, but programmer sees it in the code and tools like linters or IDEs plugins can analyze them.
- You get no guarantee that variable you get will be of a type you expect.
- That is why everyone would prefer to write in functional, strong, static typed languages like Haskell or Scala :D
Po co używać podpowiedzi typów?
::: incremental
- “type hints should be used whenever unit tests are worth writing”, cytat z cennego blog posta
- poprawiają czytelność kodu
- dokumentują kod (dla deweloperów i IDE)
- może być używane dla statycznego sprawdzenie typów
:::
Czym jest statyczne sprawdzanie typów?
When (most) functions (and variables) are annotated with type(s) one can check, without running a program, the compatibility. In static languages the correctness of types is checked during compilation (Java, C++, Haskell, C#). But this is not the case in Python. We just run the code and hope for the best. This gives flexibility but can also raise some runtime issues.
However, using hints we can statically check types compatibility before actually running code. The tool for that is called mypy.
Modyfikacja requirments(in)
requirements.txt
mypy-extensions==0.4.3
mypy==0.931
typing-extensions==3.10.0.2
Integracja z CI/CD
- Github - przykładowy kod github action.
jobs:
build:
runs-on: ubuntu-latest
name: Mypy
steps:
- uses: actions/checkout@v1
- name: Set up Python 3.8
uses: actions/setup-python@v1
with:
python-version: 3.8
- name: Install Dependencies
run: |
pip install mypy
- name: mypy
run: |
mypy src/
Możliwe problemy
Dostaję błąd “stubs are missing” dla poszczególnych bibliotek
Nie wszystkie biblioteki mają wbudowane sugerowane type. Mamy dwie opcje:
- Znaleźć bibliotekę, która dodaje typy do stubsów (np. dla pandas https://github.com/VirtusLab/pandas-stubs)
- Poinstruuować mypy żeby ignorować podpowiedzi dla danej biblioteki
import pandas as pd # type: ignore
Więcej informacji tutaj
Możliwe problemy
Funkcja korzysta z argumentu/zwraca słownik z różnymi typami
Są dwa rozwiązania:
- możemy być bardzo liberalni
Dict[str, Optional[str, float]]
- albo bardzo zachowawczy definiując klasę, w której konkretnie podamy jakie są klucze i jakiego typu mają one wartości
Na dłuższą metę drugie rozwiązanie jest lepsze, wyklucza możliwość modyfikacji, które mogłyby zepsuć kod zależący od naszej funkcji.
Więcej na tematy mypy i typowania w Pythonie
- Great overview, as usual on realpython. https://realpython.com/python-type-checking/
- All the builtin types that are available https://mypy.readthedocs.io/en/stable/builtin_types.html
- mypy docs
- style guide for annotations https://google.github.io/styleguide/pyguide.html#319-type-annotations
- valuable blog post https://bernat.tech/posts/the-state-of-type-hints-in-python/