# Python typing module Note: Ahoj, vitam vas na prvej prezentacii v mojom zivote ku ktorej som sa upisal dobrovolne. Nastastie tema bola dobrovolna tiez a tak sa mozme venovat typing modulu. Uz ho pouzivame v par komponentach takze vas nebudem nudit zakladmi a pustime sa viac menej hned do zaujimavych casti. --- ## Motivation - documentation is being kept up-to-date - IDE / mypy can hint some errors - explicitly said what data is expected Note: Ale pred tym este pripomienka preco to cele robime. Typova informacia je v podstate sucast dokumentacie kodu - dava nam informaciu ktoru nemusime zlozito zistovat ci uz z implementacie alebo z prikladu volania funkcie v inej casti kodu. Problem je ze dokumentacia zastarava a je tazke udrziavat ju presnu (co byva aj moj problem, skontrolovat ci docstring stale odpoveda funkcionalite aj po oprave bugu etc..). V tomto je podla mna najvacsia vyhoda typehintingu, pri spravnej konfiguracii mypy a zaclenenia do pipeline sa nestane ze deklarovany typ sa rozide s realitou. Samozrejme IDEcka toho hojne vyuzivaju a dokazu poskytovat napovedu, upozornit na chyby, vsetko veci ktore sa hodia. --- # Deep dive Note: Deep dive - ako funguje typovanie v pythne? --- ## Function annotations `__annotations__` attribute ```python def fnc(x: int) -> int: return x print (fnc.__annotations__) ``` <!-- .element: class="fragment fade-up" data-fragment-index="1" --> ```python >>> {'x': <class 'int'>, 'return': <class 'int'>} ``` <!-- .element: class="fragment fade-up" data-fragment-index="2" --> ```python def fnc(x: '2', y: '2') -> '9': return x + y print (fnc.__annotations__) >>> {'x': '2', 'y': '2', 'return': '9'} ``` <!-- .element: class="fragment fade-up" data-fragment-index="3" --> more info @ [PEP 3107](https://www.python.org/dev/peps/pep-3107/) <!-- .element: class="fragment fade-up" data-fragment-index="4" --> Note: Skrz __annotations__ attribut. Koncept je jednoduchy - python ocakava vyraz, ten vyhodnoti a jeho vysledok ulozi do slovnika. Nic viac, nic menej. Any expression can be in annotation, it will be evaluated on start. The return key was chosen because it cannot conflict with the name of a parameter. --- ## Problems: - evaluation at function definition time - forward references - unnecessary overhead at runtime ```python def do_something(x: 'A') -> 'B': ``` ## Solution? <!-- .element: class="fragment fade-up" data-fragment-index="1" --> python >=3.7 and [PEP563](https://www.python.org/dev/peps/pep-0563/) <!-- .element: class="fragment fade-up" data-fragment-index="2" --> `from __future__ import annotations` <!-- .element: class="fragment fade-up" data-fragment-index="3" --> Note: Can be mitigated by TYPE_CHECKING constant Annotations not evaluated, kept as string - checker evaluates them. It was done cuz of forward references anyway. --- ## Variable annotations - python < 3.6 ```python x = "abcd" # type: str ``` - python >= 3.6 ```python x: str = "abcd" ``` more @ [PEP484](https://www.python.org/dev/peps/pep-0484/#id50) (type comments) and [PEP526](https://www.python.org/dev/peps/pep-0526/) (py3.6 syntax) <!-- .element: class="fragment fade-up" data-fragment-index="1" --> Note: Variable declaration w/0 definition -> `a: int` instead of `a = None; ... ; a = 5` (more explicit syntax, mypy would complain about missing `Optional`) --- # Tricky stuff --- ## Annotating tuple - simulating `record` type <!-- .element: class="fragment fade-up" data-fragment-index="1" --> ```python x: Tuple[int, str] = 5, 'str' y: Tuple[int, ...] = 1,2,3 ``` <!-- .element: class="fragment fade-up" data-fragment-index="1" --> - use `Sequence[T]` instead (at least for annotating arguments) <!-- .element: class="fragment fade-up" data-fragment-index="2" --> --- ## Invariance vs covariance error > Covariance and contravariance are terms that refer to the ability to use a more specific or a less specific type than originally specified — Microsoft (shortened) --- ### Rules of thumb - immutable containers == mostly covariant - mutable containers == mostly invariant --- ## TypeVar and generics - value restriction and `bound` kw argument <!-- .element: class="fragment fade-up" data-fragment-index="1" --> ```python X = TypeVar('X', int, str) def add(a: X, b: X) -> X: return a + b ``` <!-- .element: class="fragment fade-up" data-fragment-index="2" --> --- ## Nice to know stuff - Type - NewType - Overloads - Protocols and structural subtyping - `reveal` functions (mypy specific) - `TypedDict` Note: NewType - like new class but with no overhead, better than type aliasing Overload - decorator, ignored at runtime e.g ```python @overload def x(int, str): ... @overload def x(int, int): ... def x(a, b): ... ``` reveal_type, reveal_locals TypedDict, optional keyword arg --- # Typing related stuffs --- ## Stubs ```python x: int def func_1(code: str) -> int: ... def func_2(a: int, b: int = ...) -> int: ... ``` <!-- .element: class="fragment fade-up " data-fragment-index="1" --> [typeshed](https://github.com/python/typeshed) repo <!-- .element: class="fragment fade-up" data-fragment-index="2" --> more info @ [mypy wiki](https://github.com/python/mypy/wiki/Creating-Stubs-For-Python-Modules) <!-- .element: class="fragment fade-up" data-fragment-index="3" --> --- ## Packaging typed project - `py.typed` marker - more info @ [PEP561](https://www.python.org/dev/peps/pep-0561/) or @ [mypy section about packaging](https://mypy.readthedocs.io/en/latest/installed_packages.html) Note: W/0 marker it will seem as untyped. 3 types of granularity - inline types, stub files alongside of code (.pyi), stubs only package. Example: clown MR (but mypy tutorial should be enough) --- ## Automatic annotation - with extensive test suite it can approximate annotations - [stubgen](https://github.com/python/mypy/blob/master/mypy/stubgen.py) (mypy), [pyAnnotate](https://github.com/dropbox/pyannotate) (dropbox), [MonkeyType](https://github.com/Instagram/MonkeyType) (Instagram) Note: comes with overhead so it shouldnt be done in production --- ## Future of typing - py3.8 - native `TypedDict` - `Literal` type - `final` modificator - py4.0 - native postponed annotations - native container types? --- ## Typing mantra - be as precise as you can - abstract inputs, specific outputs - sensible disallows - use postponed annotations on 3.7 --- # Questions? --- ## Well then, thank you for your attention!
{"metaMigratedAt":"2023-06-14T23:51:42.977Z","metaMigratedFrom":"Content","title":"Python typing module","breaks":true,"contributors":"[{\"id\":\"f36f04e9-926f-4415-afba-6ff21dcc306d\",\"add\":8490,\"del\":2036}]"}
    494 views