Wyślij zapytanie Dołącz do Sii

W pracy z kodem kluczowa jest jego dobra czytelność, a jawne deklarowanie typów zmiennych może znacznie w tym pomóc. To właśnie type hinting (wskazówki typu) pełni tę rolę w języku Python. Ta funkcjonalność, będąca częścią standardowej biblioteki Pythona, jest łatwa w użyciu dzięki wsparciu ze strony jego składni. Dzięki temu każdy, niezależnie od środowiska deweloperskiego i poziomu znajomości języka, może z niej skorzystać.

Mam nadzieję, że ten artykuł zachęci Was do używania wskazówek typu.

Dlaczego warto dbać o czytelność kodu w Pythonie

Zazwyczaj Python kojarzy się z tworzeniem skryptów, interpretowanym kodem (a dokładniej kodem bajtowym powstałym z kompilacji) i również dynamicznym typowaniem, czyli przypisywanym typu zmiennej podczas wykonywania programu, a nie przed jego wykonaniem.

Jeśli język jest dynamicznie typowany, to w jakim celu definiować w kodzie typy? Nawet standard C++ w wersji 11 zmienił znaczenie słowa kluczowego auto i od tej wersji można używać go jako zastępczy typ zmiennej. Jednak w C++ najczęściej to mniejszość kodu oznaczona jest typem auto, a kompilacja mimo wszystko zweryfikuje zgodność typów w kodzie.

W przypadku programu czy skryptu gdzie typ żadnej zmiennej nie jest jasno określony i nie jest weryfikowany na etapie kompilacji, dość łatwo można stworzyć problematyczny kod, gdzie dodatkowo bez pokrycia testami jednostkowymi, rozrośnięty projekt może być pełen błędów i trudny w utrzymaniu.

Czym jest type hinting

Python jest dynamicznie typowanym językiem. Mimo wszystko istnieje możliwość deklarowania typu poprzez type hinting, a funkcjonalność ta została wprowadzona oficjalnie w wersji Pythona 3.5.

To rozwiązanie pozwala na wskazywanie typów elementów takich jak:

  • zmienne,
  • pola klas,
  • argumenty i typy zwracane dla funkcji oraz metod.

Warto pamiętać, że wskazówki typu to jednak tylko wskazówki i nie wpływają one na wykonywanie programu. Mimo wszystko takie rozwiązanie polepsza czytelność kodu, a samo IDE (Integrated Development Environments) często wspiera type hints i umożliwia na przykład autouzupełnianie kodu. W połączeniu ze statyczną analizą kodu, o której dowiecie się w innym artykule na blogu Sii: Statyczna analiza kodu w Pythonie, można również sprawdzić kod pod kątem błędów, w tym związanych z typami zmiennych.

Wspierane typy

Deklarować można typy wbudowane: str, bool, float, int. Wspierane są również różnego typu kontenery: List, Dict, Set, Tuple. Python nie ogranicza nas w łączeniu wskazówek, można zdefiniować np.: List[str], czy też Dict[str, List[str]]. Czasem wspierane są zmienne kilku typów, użyteczne wtedy okaże się Union, z pomocą którego możemy zadeklarować na przykład parametr Union[float, int] obsługujący oba typy prymitywne. Jeśli wspierane są zmienne każdego typu, można to jawnie oznaczyć poprzez użycie Any.

Każda klasa zdefiniowana w naszym kodzie również może być użyta w deklaracji typu.

Nie wszystkie metody muszą zwrócić wynik – w takim wypadku można zwrócić wartość Optional(na przykład Optional[str]).

Przykład użycia

Załóżmy, że chcemy stworzyć skrypt do klasyfikacji plików na podstawie ich rozszerzenia.

Jedną z funkcji którą moglibyśmy zdefiniować wygląda tak:

```
def is_text_file(path):
    return path.endswith(".txt")
```

IDE (w moim przypadku Visual Studio Code) nie podpowie, co mogę zrobić ze zmienną:

code

Używając wskazówek typu, w tym wypadku dla argumentu oraz typu zwracanego, możemy zmienić kod na:

```
def is_text_file(path: str) -> bool:
    return path.endswith(".txt")
```
code

IDE rozpoznaje teraz i podpowiada, co można zrobić ze zmienną typu str.

IDE również podpowiada przy wywołaniach metody, jeśli chcemy skorzystać z funkcji:

code

Z biegiem czasu może przybywać funkcjonalności w skrypcie lub będziemy chcieli listować pliki tekstowe z danego folderu.

Zdefiniujemy więc klasę Directory. Niech metoda inicjalizująca przyjmuje listę nazw plików, oznaczając to wskazówką typu. W metodzie zwracającej listę plików tekstowych IDE jest w stanie wydedukować, że iterowana jest lista, a jej pojedynczy element został oznaczony jako str, więc znowu prawidłowo podpowie metodę endswith. Jeśli konstruktor nie będzie zawierał tej wskazówki, IDE nie będzie w stanie nic podpowiedzieć.

code

To są najbardziej podstawowe użycia wskazówek typu, a już w dużej części umożliwiają pracę z kodem, jak przy językach ze statycznym typowaniem. Nawigacja w kodzie, posiadając ciągi wywołań różnych metod, będzie z takim rozwiązaniem znacznie łatwiejsza. Zamiast wyszukiwać spodziewanego typu argumentu na podstawie jednego z wywołań danej metody, od razu widoczny jest typ, którego się spodziewamy.

Zmiany między wersjami

Funkcjonalność ta oczywiście zmieniała się między wersjami Pythona. Zmiany są w przystępny sposób opisane w sekcjach „What’s new” na oficjalnej stronie dokumentacji do tego języka, (przykład dla wersji 3.5).

Jeśli chodzi o aspekt type hinting, zmieniały się między innymi następujące rzeczy:

  • Python 3.7:
    • poprawa wydajności – czas importowania modułu typing zredukowany 7-krotnie,
    • naprawa błędów.
  • Python 3.8
    • lepsze wsparcie dla słowników (dict),
    • wsparcie dla literałów,
    • wsparcie dla zmiennych finalnych (oznaczanych poprzez Final).
  • Python 3.9
    • ulepszone wsparcie dla typów generycznych (list, zamiast List itd., dzięki czemu nie jest już potrzebne importowanie modułu typing),
    • poprawki do literałów.
  • Python 3.10
    • wsparcie dla Callable oraz powiązanego z nim Concatenate,
    • możliwość użycia operatora “|” zamiast Union,
    • dodano “type guarding”, funkcje wspomagające zawężać typ zmiennej.
  • Python 3.11
    • wsparcie dla self (w postaci Self).

Warto zaznaczyć, że jest to jedynie część wprowadzonych zmian dla modułu typing. Wybrałem te, które moim zdaniem najczęściej będą używane przez użytkowników. Aby sprawdzić wszystkie zmiany, warto zobaczyć wspomniane wcześniej sekcje “What’s new” dokumentacji Pythona dla wersji 3.5 i wyżej.

Podsumowanie

Dodanie wskazówek typu do kodu w małym skrypcie może nie przynieść ogromnych korzyści. Jednak w średnim, a tym bardziej większym projekcie może znacznie ułatwić i przyspieszyć pracę w całym zespole bardzo małym kosztem.

Aby korzystać z deklaracji typów, nie trzeba instalować dodatkowych bibliotek, a większość środowisk posiada już wersję Pythona wspierającą tę funkcjonalność. Co więcej, do faktycznej walidacji czy kod używany jest zgodnie z deklaracjami typu, można korzystać z narzędzi typu „static type checker”.

Sama funkcjonalność oznaczania typów w Pythonie jest rozwijana między innymi z myślą o narzędziach do statycznej analizy kodu, a jednym z nich jest stworzony przez Microsoft “pyright”, możliwy do zainstalowania za pomocą “pip”.

Z takim zestawem narzędzi praca z kodem może być znacznie ułatwiona. A co najważniejsze – wskazówki typu nie są obowiązkowe i nie jest konieczne oznaczenie całego projektu. To rozwiązanie daje elastyczność użytkownikowi. Krytyczna i wrażliwa część kodu może posiadać wskazówki, a mniej istotne części można pominąć, jak np.: oznaczanie typu str jako zwracanego z tak zwanej magicznej metody __str__. Takie podejście pozwoli na zrównoważenie zysków płynących z użycia tej funkcjonalności i czasu potrzebnego na jej wdrożenie oraz utrzymanie.

5/5 ( głosy: 5)
Ocena:
5/5 ( głosy: 5)
Autor
Avatar
Jakub Jabłoński

Absolwent kierunku Informatyka na Politechnice Gdańskiej. Programista z 7-letnim doświadczeniem, entuzjasta automatyzacji, zwłaszcza w obszarze testowania oprogramowania. W ramach hobby oddaje się gotowaniu

Zostaw komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Może Cię również zainteresować

Pokaż więcej artykułów

Bądź na bieżąco

Zasubskrybuj naszego bloga i otrzymuj informacje o najnowszych wpisach.

Otrzymaj ofertę

Jeśli chcesz dowiedzieć się więcej na temat oferty Sii, skontaktuj się z nami.

Wyślij zapytanie Wyślij zapytanie

Natalia Competency Center Director

Get an offer

Dołącz do Sii

Znajdź idealną pracę – zapoznaj się z naszą ofertą rekrutacyjną i aplikuj.

Aplikuj Aplikuj

Paweł Process Owner

Join Sii

ZATWIERDŹ

This content is available only in one language version.
You will be redirected to home page.

Are you sure you want to leave this page?