Déclaration des types
🤓

Déclaration des types

📑 Le petit mot du père MEVAERE

Python est un langage dynamique, c'est-à-dire que chaque variable est en fait un objet complexe qui "s'adapte" à son contenu.

Conséquences

  • c'est une des raisons pour laquelle Python est un langage de programmation plutôt lent ;
  • pour les projets importants, le côté dynamique laisse passer beaucoup de bugs alors que des langages comme C/C++ ou Delphi n'auraient jamais accepté la compilation.

Avantage de la déclaration des types des variables

  • cela permet de prendre de bonnes habitudes de programmation ;
  • cela rend lisible votre code pour vos camarades ;
  • mypyc, ou votre IDE peut détecter des erreurs triviales ;
  • cela permet d'optimiser violemment l'exécution des programmes en convertissant / compilant votre code en C.

Désavantages de la déclaration des types des variables

  • cela prend du temps lors de l'écriture du programme ;
  • cela ralentit le code ;
  • c'est souvent inutile quand on se sert de Python pour des petits projets ou des calculs scientifiques ;
  • cela ne change ABSOLUMENT pas la manière dont l'interpréteur interprète le code.

Déclaration des types de base

x: int = 1
x: float = 1.0
x: bool = True
x: str = "test"
x: bytes = b"test"

Déclaration des List, Set, Dict, Tuple

from typing import List, Set, Dict, Tuple, Optional

x: List[int] = [1]
x: Set[int] = {6, 7}
x = [1]  # type: List[int]

x: Dict[str, float] = {'field': 2.0}
x: Tuple[int, str, float] = (3, "yes", 7.5)
x: Tuple[int, ...] = (1, 2, 3)

# Use Optional[] for values that could be None
x: Optional[str] = some_function()

Fonctions

from typing import Callable, Iterator, Union, Optional, List

def f(num1: int, my_float: float = 3.5) -> float:
    return num1 + my_float

# Annotation d'une fonction (Callable)
x: Callable[[int, float], float] = f

# Générateur
def g(n: int) -> Iterator[int]:
    i = 0
    while i < n:
        yield i
        i += 1

Niveau avancé

from typing import Union, Any, List, Optional, cast

# Si il y a plusieurs possibilités
x: List[Union[int, str]] = [3, 5, "test", "fun"]

# Any si ça peut tout être
x: Any = mystery_function()

# This makes each positional arg and each keyword arg a "str"
def call(self, *args: str, **kwargs: str) -> str:

# On ajoute "type: ignore" en commentaire pour supprimer l'erreur,
x = confusing_function()  # type: ignore

# "cast" est une fonction qui permet de passer outre ce que mypyc devine
a = [4]
b = cast(List[int], a)  # Passes fine
c = cast(List[str], a)  # Passes fine (no runtime check)
reveal_type(c)  # -> Revealed type is 'builtins.list[builtins.str]'
print(c)  # -> [4]; the object is not cast

Standard “duck types”

from typing import Mapping, MutableMapping, Sequence, Iterable, List, Set

# Iterable
def f(ints: Iterable[int]) -> List[str]:
    return [str(x) for x in ints]

f(range(1, 3))

Classes

class MyClass:
    attr: int
    charge_percent: int = 100

    def __init__(self) -> None:
        ...

    def my_method(self, num: int, str1: str) -> str:
        return num * str1

# User-defined classes are valid as types in annotations
x: MyClass = MyClass()

# You can use the ClassVar annotation to declare a class variable
class Car:
    seats: ClassVar[int] = 4
    passengers: ClassVar[List[str]]

# You can also declare the type of an attribute in "__init__"
class Box:
    def __init__(self) -> None:
        self.items: List[str] = []

Divers

import sys
import re
from typing import Match, AnyStr, IO

# "typing.Match" describes regex matches from the re module
x: Match[str] = re.match(r'[0-9]+', "15")

# Use IO[] for functions that should accept or return any
# object that comes from an open() call (IO[] does not
# distinguish between reading, writing or other modes)
def get_sys_IO(mode: str = 'w') -> IO[str]:

# Forward references are useful if you want to reference a class before
# it is defined
def f(foo: A) -> int:  # This will fail
    ...

class A:
    ...

# If you use the string literal 'A', it will pass as long as there is a
# class of that name later on in the file
def f(foo: 'A') -> int:  # Ok
    ...

Décorateurs

from typing import Any, Callable, TypeVar

F = TypeVar('F', bound=Callable[..., Any])

def bare_decorator(func: F) -> F:
    ...

def decorator_args(url: str) -> Callable[[F], F]:
    ...