# Le typage L'activité consiste en un TD comprenant un __cours dirigé__ et des __exercices__ relatifs au __typage__ en Python. ## Pré-requis Avoir effectué l'activité sur les [f-strings](../chapitre_5/) et les [fonctions](../chapitre_4/) ## Consignes 1. Télécharger le fichier [TD.ipynb](./TD.ipynb), 2. Se rendre sur [Basthon](https://notebook.basthon.fr/), 3. Ouvrir le fichier TD.ipynb téléchargé, 4. Suivre le déroulé du TD, les réponses sont à mettre directement dans votre fichier, 5. À la fin de la séance, n'oubliez pas de sauvegarder votre fichier sur votre clé USB ou espace personnel. --------- ## Mémo — Le typage ### Rappel : les types de base en Python Toute valeur en Python possède un **type**. Les types de base vus en [chapitre 1](../chapitre_1/) sont : | Type | Description | Exemple | |------|-------------|---------| | `int` | Entier relatif | `42`, `-7`, `0` | | `float` | Nombre décimal | `3.14`, `-0.5` | | `str` | Chaîne de caractères | `"Bonjour"`, `'NSI'` | | `bool` | Booléen | `True`, `False` | ```python type(42) # → type(3.14) # → type("Bonjour") # → type(True) # → ``` --- ### Typage dynamique Python est un langage à **typage dynamique** : le type d'une variable n'est pas déclaré à l'avance, il est déterminé **au moment de l'exécution**, selon la valeur qu'on lui affecte. ```python x = 42 # x est un int print(type(x)) # → x = "Bonjour" # x devient un str (la même variable change de type !) print(type(x)) # → ``` C'est différent des langages à **typage statique** comme C ou Java, où le type est déclaré une fois pour toutes : ```c // En C : le type est fixé dès la déclaration int x = 42; x = "Bonjour"; // ERREUR de compilation ``` | | Typage dynamique | Typage statique | |--|--|--| | Exemples | Python, JavaScript | C, Java, Rust | | Type déclaré ? | Non | Oui | | Erreurs de type | À l'exécution | À la compilation | | Flexibilité | Élevée | Faible | --- ### Vérifier le type : `type()` et `isinstance()` #### `type()` Retourne le type exact d'une valeur. ```python x = 42 print(type(x)) # → print(type(x) == int) # → True print(type(x) == str) # → False ``` #### `isinstance()` Vérifie si une valeur est d'un type donné. **À préférer** dans les programmes car plus robuste. ```python x = 42 print(isinstance(x, int)) # → True print(isinstance(x, float)) # → False print(isinstance(x, str)) # → False # isinstance accepte aussi un tuple de types print(isinstance(x, (int, float))) # → True (int ou float) ``` Cas utile : valider une saisie utilisateur. ```python def verifier_age(valeur): if not isinstance(valeur, int): return "Erreur : l'âge doit être un entier." if valeur < 0 or valeur > 130: return "Erreur : âge invalide." return f"Âge valide : {valeur} ans." print(verifier_age(17)) # → Âge valide : 17 ans. print(verifier_age("dix-sept")) # → Erreur : l'âge doit être un entier. ``` --- ### Les annotations de type Depuis Python 3.5, on peut **annoter** les types des paramètres et du retour d'une fonction. Ces annotations sont **facultatives** : Python ne les vérifie pas à l'exécution, mais elles servent de **documentation** et aident les outils de développement. #### Syntaxe ```python def nom_fonction(parametre: type_attendu) -> type_retour: ... ``` #### Exemples ```python def aire_rectangle(longueur: float, largeur: float) -> float: return longueur * largeur def est_pair(n: int) -> bool: return n % 2 == 0 def saluer(prenom: str) -> str: return f"Bonjour {prenom} !" ``` On peut aussi annoter des variables : ```python age: int = 17 nom: str = "Alice" scores: list = [10, 15, 12] ``` #### Pourquoi annoter ? ```python # Sans annotation : que doit-on passer ? Qu'est-ce qui est retourné ? def transformer(x): return x * 2 # Avec annotation : c'est immédiatement clair def transformer(x: int) -> int: return x * 2 ``` Les annotations permettent de : - **Documenter** le code (qui lit la fonction sait quoi passer) - **Détecter des erreurs** avec des outils comme `mypy` - **Faciliter la maintenance** du code sur le long terme --- ### Erreurs de type courantes #### Opération sur des types incompatibles ```python age = input("Votre âge : ") # input() retourne TOUJOURS un str print(age + 1) # TypeError : on ne peut pas additionner str et int ``` Solution : convertir avec `int()`. ```python age = int(input("Votre âge : ")) print(age + 1) # Correct ``` #### Confusion entre `str` et `int` ```python a = "5" b = "3" print(a + b) # → "53" (concaténation de chaînes !) print(int(a) + int(b)) # → 8 (addition d'entiers) ``` --- ### Conversion de types (rappel) | Conversion | Fonction | Exemple | |---|---|---| | Vers entier | `int()` | `int("42")` → `42` | | Vers flottant | `float()` | `float("3.14")` → `3.14` | | Vers chaîne | `str()` | `str(42)` → `"42"` | | Vers booléen | `bool()` | `bool(0)` → `False` | Valeurs considérées comme `False` par `bool()` : ```python bool(0) # False bool(0.0) # False bool("") # False (chaîne vide) bool([]) # False (liste vide) bool(None) # False # Tout le reste est True ``` --- ### Exemple complet : fonction bien typée ```python def calculer_moyenne(notes: list) -> float: """ Calcule la moyenne d'une liste de notes. Paramètres : notes (list) : liste de nombres (int ou float) Retourne : float : la moyenne, ou 0.0 si la liste est vide """ if not isinstance(notes, list): raise TypeError("notes doit être une liste") if len(notes) == 0: return 0.0 return sum(notes) / len(notes) # Utilisation mes_notes = [12, 15, 9, 17, 14] print(f"Moyenne : {calculer_moyenne(mes_notes):.2f}") # → Moyenne : 13.40 ``` --- ### Résumé | Notion | Ce qu'il faut retenir | |---|---| | Typage dynamique | Le type est déterminé à l'exécution, pas à la déclaration | | `type(x)` | Retourne le type exact de `x` | | `isinstance(x, T)` | Vérifie si `x` est du type `T` (à préférer à `type()`) | | Annotations | Facultatives, servent de documentation, pas vérifiées par Python | | `input()` | Retourne **toujours** un `str` — penser à convertir | --------- ## Pour aller plus loin Félicitations ! Vous avez terminé le module de programmation Python. Pour approfondir le typage en Python : [PEP 484 — Type Hints](https://peps.python.org/pep-0484/)