🔝 Retour au Sommaire
Python est un langage à typage dynamique : vous n'avez pas besoin de déclarer le type de vos variables. Python le détermine automatiquement au moment de l'exécution. C'est l'une des raisons pour lesquelles Python est si facile à apprendre !
# Python détermine automatiquement les types
age = 25 # int
nom = "Alice" # str
prix = 19.99 # float Cependant, cette flexibilité peut aussi être source de confusion, surtout dans les grands projets. C'est là qu'interviennent les type hints (indications de type).
Les type hints permettent d'indiquer quel type de données est attendu, sans pour autant forcer ce type. Ils servent de documentation et permettent aux outils de détecter des erreurs potentielles avant l'exécution.
Point important : Les type hints sont complètement optionnels en Python. Votre code fonctionnera exactement de la même manière avec ou sans eux. Ils sont là pour vous aider, vous et les autres développeurs, à comprendre le code.
-
Meilleure lisibilité : Le code se documente lui-même
# Sans type hints def calculer_prix(prix, quantite, remise): return prix * quantite * (1 - remise) # Avec type hints (beaucoup plus clair !) def calculer_prix(prix: float, quantite: int, remise: float) -> float: return prix * quantite * (1 - remise)
-
Détection d'erreurs : Les IDE et outils comme mypy peuvent détecter des bugs avant l'exécution
def additionner(a: int, b: int) -> int: return a + b # L'IDE vous avertira que ce n'est pas correct resultat = additionner("5", "3") # Erreur détectée !
-
Autocomplétion améliorée : Votre IDE sait quels attributs et méthodes suggérer
-
Documentation vivante : Les types sont toujours à jour, contrairement aux commentaires
-
Refactoring plus sûr : Changez le code en sachant que les outils détecteront les incompatibilités
- ✅ Dans les fonctions publiques (API de votre code)
- ✅ Dans les projets professionnels ou de taille moyenne/grande
- ✅ Quand vous travaillez en équipe
- ❌ Pas obligatoire pour de petits scripts personnels
- ❌ Pas nécessaire lors de l'apprentissage initial (mais bon à connaître !)
Depuis Python 3.6, vous pouvez annoter les variables :
# Syntaxe : nom_variable: type = valeur
age: int = 25
nom: str = "Alice"
prix: float = 19.99
est_actif: bool = True Note : Vous pouvez aussi annoter sans assigner immédiatement :
age: int
nom: str
# Plus tard dans le code
age = 25
nom = "Alice" La syntaxe pour les fonctions :
def nom_fonction(param1: type1, param2: type2) -> type_retour:
# Code
return valeurExemples :
def additionner(a: int, b: int) -> int:
"""Additionne deux nombres entiers."""
return a + b
def saluer(nom: str) -> str:
"""Retourne un message de salutation."""
return f"Bonjour {nom} !"
def afficher_message(texte: str) -> None:
"""Affiche un message (ne retourne rien)."""
print(texte)Note : -> None indique qu'une fonction ne retourne rien (ou retourne None).
def exemples_types_base():
# Nombres entiers
nombre: int = 42
# Nombres décimaux
prix: float = 19.99
# Chaînes de caractères
nom: str = "Alice"
# Booléens
est_valide: bool = True
# None (absence de valeur)
resultat: None = NoneDepuis Python 3.10, les types génériques s'écrivent directement avec les types natifs. Plus besoin d'importer depuis le module typing pour les cas courants.
💡 Dans du code plus ancien (Python < 3.9), vous verrez
from typing import List, Dict, Tuple, Set. C'est la même chose, juste l'ancienne syntaxe.
Pour indiquer une liste d'éléments d'un type spécifique :
# Liste d'entiers
nombres: list[int] = [1, 2, 3, 4, 5]
# Liste de chaînes
noms: list[str] = ["Alice", "Bob", "Charlie"]
# Liste de nombres décimaux
prix: list[float] = [19.99, 29.99, 9.99]
def calculer_moyenne(notes: list[float]) -> float:
"""Calcule la moyenne d'une liste de notes."""
return sum(notes) / len(notes)Pour indiquer un dictionnaire avec types de clés et de valeurs :
# Dictionnaire : clés str, valeurs int
ages: dict[str, int] = {
"Alice": 25,
"Bob": 30,
"Charlie": 35
}
# Dictionnaire : clés str, valeurs float
prix: dict[str, float] = {
"pomme": 2.50,
"banane": 1.80,
"orange": 3.20
}
def compter_occurrences(texte: str) -> dict[str, int]:
"""Compte les occurrences de chaque mot."""
mots = texte.split()
compteur: dict[str, int] = {}
for mot in mots:
compteur[mot] = compteur.get(mot, 0) + 1
return compteurPour des tuples, vous pouvez spécifier le type de chaque élément :
# Tuple de deux éléments : str et int
personne: tuple[str, int] = ("Alice", 25)
# Tuple de trois éléments
coordonnees: tuple[float, float, float] = (10.5, 20.3, 5.8)
def obtenir_info() -> tuple[str, int, str]:
"""Retourne (nom, age, ville)."""
return "Alice", 25, "Paris"
# Pour un tuple de longueur variable avec le même type
nombres: tuple[int, ...] = (1, 2, 3, 4, 5, 6, 7, 8)# Ensemble d'entiers
nombres_uniques: set[int] = {1, 2, 3, 4, 5}
# Ensemble de chaînes
tags: set[str] = {"python", "programming", "tutorial"}
def obtenir_lettres_uniques(texte: str) -> set[str]:
"""Retourne l'ensemble des lettres uniques dans un texte."""
return set(texte.lower())La syntaxe Type | None signifie qu'une valeur peut être du type spécifié ou None.
def chercher_utilisateur(id: int) -> str | None:
"""
Cherche un utilisateur par ID.
Retourne le nom ou None si non trouvé.
"""
utilisateurs = {1: "Alice", 2: "Bob", 3: "Charlie"}
return utilisateurs.get(id)
# Variables optionnelles
nom: str | None = None # Peut être str ou None
nom = "Alice" # Maintenant c'est une str
age: int | None = None
age = 25 💡 Dans du code plus ancien, vous verrez
Optional[str](importé detyping). C'est équivalent àstr | None.
L'opérateur | permet d'indiquer qu'une valeur peut être de plusieurs types différents.
# Peut être int ou float
nombre: int | float = 42
nombre = 3.14 # OK aussi
def diviser(a: int | float, b: int | float) -> float:
"""Divise deux nombres (entiers ou décimaux)."""
return a / b
# Fonction qui peut retourner str ou int
def obtenir_valeur(cle: str) -> str | int:
valeurs = {"nom": "Alice", "age": 25}
return valeurs.get(cle, "inconnu")💡 Dans du code plus ancien, vous verrez
Union[int, float](importé detyping). C'est équivalent àint | float.
Any signifie "n'importe quel type". C'est comme ne pas mettre de type hint du tout.
from typing import Any
def traiter_donnee(donnee: Any) -> Any:
"""Accepte n'importe quel type et retourne n'importe quel type."""
# Traitement
return donnee
# Variables de type quelconque
valeur: Any = 42
valeur = "texte" # OK
valeur = [1, 2, 3] # OK aussi Conseil : Utilisez Any avec modération. C'est utile quand vous ne connaissez vraiment pas le type, mais trop l'utiliser annule les bénéfices des type hints.
object est le type parent de tous les objets en Python. Contrairement à Any, l'IDE supposera que vous n'avez accès qu'aux méthodes de base.
def afficher(valeur: object) -> None:
"""Accepte n'importe quel objet."""
print(valeur) # OK, print() accepte n'importe quoiCallable permet d'annoter des fonctions passées en paramètre.
from typing import Callable
# Callable[[types_parametres], type_retour]
# Fonction sans paramètre qui retourne int
fonction1: Callable[[], int]
# Fonction avec deux int en paramètres qui retourne str
fonction2: Callable[[int, int], str]
def appliquer_operation(
valeur: int,
operation: Callable[[int], int]
) -> int:
"""Applique une opération à une valeur."""
return operation(valeur)
def doubler(x: int) -> int:
return x * 2
def tripler(x: int) -> int:
return x * 3
resultat1 = appliquer_operation(5, doubler) # 10
resultat2 = appliquer_operation(5, tripler) # 15 from collections.abc import Callable
def transformer_liste(
liste: list[int],
fonction: Callable[[int], int]
) -> list[int]:
"""Transforme chaque élément d'une liste."""
return [fonction(x) for x in liste]
def carre(x: int) -> int:
return x ** 2
nombres = [1, 2, 3, 4, 5]
carres = transformer_liste(nombres, carre)
print(carres) # [1, 4, 9, 16, 25] Pour des types complexes répétés, vous pouvez créer des alias :
from typing import Any
# Créer un alias avec l'affectation simple (Python 3.10+)
Vector = list[float]
Matrix = list[list[float]]
JSON = dict[str, Any]
# Python 3.12+ introduit le mot-clé type :
# type Vector = list[float]
# type Matrix = list[list[float]]
# Utiliser les alias
def additionner_vecteurs(v1: Vector, v2: Vector) -> Vector:
return [a + b for a, b in zip(v1, v2)]
def traiter_json(data: JSON) -> None:
print(data)
# Alias pour des tuples complexes
Coordonnees = tuple[float, float, float]
Personne = tuple[str, int, str] # (nom, age, ville)
def calculer_distance(p1: Coordonnees, p2: Coordonnees) -> float:
"""Calcule la distance entre deux points 3D."""
return sum((a - b) ** 2 for a, b in zip(p1, p2)) ** 0.5Pour des dictionnaires avec une structure fixe, utilisez TypedDict :
from typing import TypedDict
# Définir la structure d'un dictionnaire
class Personne(TypedDict):
nom: str
age: int
ville: str
# Utiliser le type
def creer_personne(nom: str, age: int, ville: str) -> Personne:
return {"nom": nom, "age": age, "ville": ville}
def afficher_personne(personne: Personne) -> None:
print(f"{personne['nom']}, {personne['age']} ans, {personne['ville']}")
# L'IDE vous aidera avec l'autocomplétion
alice: Personne = {
"nom": "Alice",
"age": 25,
"ville": "Paris"
}
afficher_personne(alice)from typing import TypedDict
class Utilisateur(TypedDict, total=False):
nom: str # Obligatoire
age: int # Obligatoire
email: str | None # Optionnel
telephone: str | None # OptionnelLes génériques permettent de créer des fonctions et classes qui fonctionnent avec n'importe quel type.
from typing import TypeVar
# Créer une variable de type générique
T = TypeVar('T')
def premier_element(liste: list[T]) -> T:
"""Retourne le premier élément d'une liste, quel que soit son type."""
return liste[0]
# Fonctionne avec n'importe quel type
nombres = [1, 2, 3]
premier = premier_element(nombres) # Type inféré : int
mots = ["hello", "world"]
premier_mot = premier_element(mots) # Type inféré : str from typing import TypeVar
T = TypeVar('T')
U = TypeVar('U')
def creer_paire(premier: T, second: U) -> tuple[T, U]:
"""Crée une paire de deux éléments de types potentiellement différents."""
return (premier, second)
paire1 = creer_paire("Alice", 25) # Tuple[str, int]
paire2 = creer_paire(3.14, True) # Tuple[float, bool] from typing import TypeVar, Generic
T = TypeVar('T')
class Pile(Generic[T]):
"""Pile générique qui peut contenir n'importe quel type."""
def __init__(self) -> None:
self._items: list[T] = []
def empiler(self, item: T) -> None:
self._items.append(item)
def depiler(self) -> T:
return self._items.pop()
def est_vide(self) -> bool:
return len(self._items) == 0
# Utilisation
pile_nombres: Pile[int] = Pile()
pile_nombres.empiler(1)
pile_nombres.empiler(2)
print(pile_nombres.depiler()) # 2
pile_mots: Pile[str] = Pile()
pile_mots.empiler("hello")
pile_mots.empiler("world")
print(pile_mots.depiler()) # "world" Literal permet de spécifier des valeurs exactes acceptables :
from typing import Literal
def definir_mode(mode: Literal["debug", "production"]) -> None:
"""Le mode doit être exactement 'debug' ou 'production'."""
print(f"Mode : {mode}")
definir_mode("debug") # OK
definir_mode("production") # OK
# definir_mode("test") # Erreur détectée par mypy !
# Avec des nombres
def definir_niveau(niveau: Literal[1, 2, 3]) -> None:
print(f"Niveau : {niveau}")
definir_niveau(2) # OK
# definir_niveau(5) # Erreur !Final indique qu'une variable ne devrait jamais être réassignée :
from typing import Final
PI: Final = 3.14159
MAX_TENTATIVES: Final[int] = 3
# PI = 3.14 # mypy détectera cette erreur !
def utiliser_constante() -> None:
print(f"Pi vaut {PI}")from typing import ClassVar
class Compteur:
# Attribut de classe (partagé par toutes les instances)
total: ClassVar[int] = 0
# Attribut d'instance
valeur: int
def __init__(self, valeur: int) -> None:
self.valeur = valeur
Compteur.total += 1
def incrementer(self) -> None:
self.valeur += 1
c1 = Compteur(10)
c2 = Compteur(20)
print(Compteur.total) # 2 Combiner type hints et valeurs par défaut :
def creer_liste(
elements: list[int] | None = None,
taille: int = 10
) -> list[int]:
"""Crée une liste avec des éléments ou une liste vide."""
if elements is None:
return [0] * taille
return elements
def saluer(
nom: str = "Anonyme",
titre: str = "M."
) -> str:
return f"Bonjour {titre} {nom}"from typing import Any
def somme(*nombres: int) -> int:
"""Somme un nombre variable d'entiers."""
return sum(nombres)
def afficher_infos(**infos: str) -> None:
"""Affiche des informations (clés et valeurs str)."""
for cle, valeur in infos.items():
print(f"{cle}: {valeur}")
# Avec Any pour accepter n'importe quel type
def fonction_flexible(*args: Any, **kwargs: Any) -> None:
print(args)
print(kwargs)mypy est un outil qui vérifie la cohérence des type hints dans votre code.
pip install mypy# Vérifier un fichier
mypy mon_script.py
# Vérifier un répertoire
mypy mon_projet/Fichier : calcul.py
def additionner(a: int, b: int) -> int:
return a + b
resultat = additionner(5, 3)
print(resultat)
# Cette ligne provoquera une erreur mypy
resultat2 = additionner("5", "3") # Erreur !Exécution de mypy :
$ mypy calcul.py
calcul.py:7: error: Argument 1 to "additionner" has incompatible type "str"; expected "int"
calcul.py:7: error: Argument 2 to "additionner" has incompatible type "str"; expected "int" Créez un fichier mypy.ini ou setup.cfg :
[mypy]
python_version = 3.10
warn_return_any = True
warn_unused_configs = True
disallow_untyped_defs = True Vous ne pouvez pas annoter directement les compréhensions, mais vous pouvez annoter la variable résultante :
# Compréhension de liste
carres: list[int] = [x**2 for x in range(10)]
# Compréhension de dictionnaire
ages: dict[str, int] = {nom: age for nom, age in [("Alice", 25), ("Bob", 30)]}
# Ou annoter dans une fonction
def generer_carres(n: int) -> list[int]:
return [x**2 for x in range(n)]Annotez d'abord les fonctions qui font partie de l'API de votre code :
# API publique : annotations obligatoires
def calculer_prix(prix_ht: float, quantite: int, tva: float = 0.20) -> float:
"""Calcule le prix TTC."""
return prix_ht * quantite * (1 + tva)
# Fonction interne privée : annotations optionnelles
def _arrondir(valeur):
return round(valeur, 2)# ❌ Difficile à lire
def traiter(data: dict[str, list[dict[str, int]]]) -> list[str]:
pass
# ✅ Plus clair avec un alias
DonneesComplexes = dict[str, list[dict[str, int]]]
def traiter(data: DonneesComplexes) -> list[str]:
passfrom typing import Any
# ❌ Trop de Any annule les bénéfices
def traiter(data: Any) -> Any:
pass
# ✅ Soyez aussi spécifique que possible
def traiter(data: dict[str, int]) -> list[str]:
pass
# ✅ Si vraiment variable, utilisez |
def traiter(data: str | int | float) -> str:
pass# ✅ Syntaxe moderne et claire
def chercher(id: int) -> str | None:
pass💡
Optional[str]importé detypingest équivalent mais moins lisible.
# Type évident : pas besoin d'annotation
nom = "Alice"
age = 25
# Type non évident : annotation utile
resultats: list[int] = []
utilisateur: str | None = None Vous n'avez pas besoin d'annoter tout d'un coup :
- Commencez par les nouvelles fonctions
- Annotez progressivement les anciennes
- Concentrez-vous sur les parties critiques
- Utilisez mypy pour détecter les incohérences
Si vous devez supporter des versions très anciennes :
def additionner(a, b):
# type: (int, int) -> int
return a + b
x = 5 # type: intQuand vous référencez une classe avant qu'elle soit définie :
class Noeud:
def __init__(self, valeur: int, suivant: "Noeud | None" = None):
self.valeur = valeur
self.suivant = suivantPython 3.7+ : Utilisez from __future__ import annotations pour éviter les guillemets :
from __future__ import annotations
class Noeud:
def __init__(self, valeur: int, suivant: Noeud | None = None):
self.valeur = valeur
self.suivant = suivantfrom dataclasses import dataclass
@dataclass
class Utilisateur:
id: int
nom: str
email: str
age: int
class GestionnaireUtilisateurs:
def __init__(self) -> None:
self._utilisateurs: dict[int, Utilisateur] = {}
self._prochain_id: int = 1
def ajouter_utilisateur(
self,
nom: str,
email: str,
age: int
) -> Utilisateur:
"""Ajoute un nouvel utilisateur."""
utilisateur = Utilisateur(
id=self._prochain_id,
nom=nom,
email=email,
age=age
)
self._utilisateurs[self._prochain_id] = utilisateur
self._prochain_id += 1
return utilisateur
def obtenir_utilisateur(self, id: int) -> Utilisateur | None:
"""Retourne un utilisateur ou None s'il n'existe pas."""
return self._utilisateurs.get(id)
def lister_utilisateurs(self) -> list[Utilisateur]:
"""Retourne la liste de tous les utilisateurs."""
return list(self._utilisateurs.values())
def filtrer_par_age(
self,
age_min: int,
age_max: int
) -> list[Utilisateur]:
"""Filtre les utilisateurs par tranche d'âge."""
return [
user for user in self._utilisateurs.values()
if age_min <= user.age <= age_max
]
# Utilisation
gestionnaire = GestionnaireUtilisateurs()
alice = gestionnaire.ajouter_utilisateur("Alice", "alice@example.com", 25)
bob = gestionnaire.ajouter_utilisateur("Bob", "bob@example.com", 30)
user = gestionnaire.obtenir_utilisateur(1)
if user:
print(f"Utilisateur trouvé : {user.nom}")
jeunes = gestionnaire.filtrer_par_age(20, 27)
print(f"Utilisateurs entre 20 et 27 ans : {len(jeunes)}") from statistics import mean, median, stdev
Nombre = int | float
Statistiques = dict[str, Nombre]
def calculer_statistiques(donnees: list[Nombre]) -> Statistiques:
"""
Calcule diverses statistiques sur une liste de nombres.
Args:
donnees: Liste de nombres (int ou float)
Returns:
Dictionnaire contenant les statistiques calculées
Raises:
ValueError: Si la liste est vide
"""
if not donnees:
raise ValueError("La liste ne peut pas être vide")
return {
"moyenne": mean(donnees),
"mediane": median(donnees),
"minimum": min(donnees),
"maximum": max(donnees),
"ecart_type": stdev(donnees) if len(donnees) > 1 else 0.0
}
def analyser_notes(notes: list[int]) -> tuple[float, list[str]]:
"""
Analyse une liste de notes et retourne la moyenne et les appréciations.
Args:
notes: Liste de notes (0-20)
Returns:
Tuple contenant (moyenne, liste d'appréciations)
"""
stats = calculer_statistiques(notes)
moyenne = stats["moyenne"]
appreciations: list[str] = []
for note in notes:
if note >= 16:
appreciations.append("Très bien")
elif note >= 14:
appreciations.append("Bien")
elif note >= 12:
appreciations.append("Assez bien")
elif note >= 10:
appreciations.append("Passable")
else:
appreciations.append("Insuffisant")
return moyenne, appreciations
# Utilisation
notes_classe = [12, 15, 8, 18, 14, 11, 16, 13]
moyenne, appreciations = analyser_notes(notes_classe)
print(f"Moyenne de la classe : {moyenne:.2f}") from typing import TypeVar, Generic, Callable
from datetime import datetime, timedelta
K = TypeVar('K') # Type de clé
V = TypeVar('V') # Type de valeur
class Cache(Generic[K, V]):
"""Cache générique avec expiration."""
def __init__(self, duree_vie: int = 300) -> None:
"""
Args:
duree_vie: Durée de vie en secondes (défaut: 5 minutes)
"""
self._cache: dict[K, tuple[V, datetime]] = {}
self._duree_vie = timedelta(seconds=duree_vie)
def set(self, cle: K, valeur: V) -> None:
"""Ajoute ou met à jour une entrée dans le cache."""
self._cache[cle] = (valeur, datetime.now())
def get(self, cle: K) -> V | None:
"""
Récupère une valeur du cache.
Returns:
La valeur si elle existe et n'est pas expirée, None sinon
"""
if cle not in self._cache:
return None
valeur, timestamp = self._cache[cle]
# Vérifier l'expiration
if datetime.now() - timestamp > self._duree_vie:
del self._cache[cle]
return None
return valeur
def get_ou_calculer(
self,
cle: K,
calculateur: Callable[[], V]
) -> V:
"""
Récupère une valeur ou la calcule si elle n'existe pas.
Args:
cle: Clé de recherche
calculateur: Fonction qui calcule la valeur si nécessaire
Returns:
La valeur (depuis le cache ou calculée)
"""
valeur = self.get(cle)
if valeur is None:
valeur = calculateur()
self.set(cle, valeur)
return valeur
# Utilisation avec différents types
cache_str: Cache[str, str] = Cache()
cache_str.set("user_1", "Alice")
print(cache_str.get("user_1"))
cache_int: Cache[int, list[int]] = Cache()
cache_int.set(1, [1, 2, 3, 4, 5])
print(cache_int.get(1)) Les type hints complètent la documentation, mais ne la remplacent pas :
def rechercher_utilisateur(
nom: str,
age_min: int | None = None,
age_max: int | None = None
) -> list[dict[str, str | int]]:
"""
Recherche des utilisateurs selon des critères.
Les type hints indiquent les types, mais la docstring explique
la logique et les cas particuliers.
Args:
nom: Nom de l'utilisateur à rechercher (insensible à la casse)
age_min: Âge minimum (inclus). Si None, pas de limite inférieure
age_max: Âge maximum (inclus). Si None, pas de limite supérieure
Returns:
Liste de dictionnaires représentant les utilisateurs trouvés.
Chaque dictionnaire contient les clés 'nom' (str) et 'age' (int).
Examples:
>>> rechercher_utilisateur("Alice")
[{'nom': 'Alice', 'age': 25}]
>>> rechercher_utilisateur("Bob", age_min=20, age_max=30)
[{'nom': 'Bob', 'age': 28}]
"""
# Implémentation
passPython n'empêche pas d'enfreindre les type hints à l'exécution :
def additionner(a: int, b: int) -> int:
return a + b
# Cela fonctionne, même si les types ne correspondent pas !
resultat = additionner("hello", "world") # "helloworld"Les type hints sont pour les outils (mypy, IDE), pas pour l'interpréteur Python.
Les type hints ont un impact minimal sur les performances. Ils sont chargés au démarrage mais n'affectent pas l'exécution.
- Python 3.9+ : syntaxe simplifiée (
list[int],dict[str, int]au lieu deList[int],Dict[str, int]) - Python 3.10+ : opérateur
|pour les unions (str | Noneau lieu deOptional[str]) - Python 3.12+ : instruction
typepour les alias de types
💡 Cette formation utilise la syntaxe Python 3.10+ (types natifs + opérateur
|). Si vous travaillez sur un projet ciblant Python < 3.9, utilisez les imports detyping.
Les type hints ajoutent de la complexité. Pour les débutants :
- Apprenez d'abord Python sans type hints
- Ajoutez-les progressivement quand vous êtes à l'aise
- Utilisez-les dans les projets professionnels
Dans cette section, nous avons appris :
✅ Type hints de base : int, str, float, bool
✅ Types génériques : list[int], dict[str, int], tuple[str, int], set[str]
✅ Types optionnels : str | None, int | float
✅ Callable : Annoter les fonctions en paramètres
✅ Type aliases : Simplifier les types complexes
✅ TypedDict : Dictionnaires avec structure fixe
✅ Génériques : TypeVar et Generic
✅ Literal et Final : Valeurs spécifiques et constantes
✅ mypy : Vérification statique des types
✅ Bonnes pratiques : Quand et comment utiliser les type hints
✅ Exemples pratiques : Applications concrètes
- Les type hints sont optionnels : votre code fonctionne sans eux
- Ils améliorent la lisibilité : le code se documente lui-même
- Ils aident les outils : IDE, mypy détectent les erreurs
- Ne sont pas forcés à l'exécution : Python reste dynamique
- Utilisez-les progressivement : commencez par les fonctions publiques
- mypy vérifie la cohérence : installez-le pour un feedback
- Utilisez la syntaxe moderne :
list[int]etstr | Nonedepuis Python 3.10+ - Documentez quand même : type hints ≠ documentation complète
Les type hints sont maintenant un standard dans le code Python professionnel. Ils :
- Facilitent la collaboration en équipe
- Réduisent les bugs en détectant les erreurs tôt
- Rendent le code plus maintenable
- Améliorent l'expérience de développement avec l'IDE
Bien qu'optionnels, ils sont devenus une bonne pratique largement adoptée dans l'industrie.
Vous maîtrisez maintenant les type hints et annotations de types ! Vous avez terminé le chapitre 1 sur les fondamentaux de Python. Dans la section suivante, nous explorerons en détail les structures de données avancées de Python.