257 lines
6.5 KiB
Markdown
257 lines
6.5 KiB
Markdown
# 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) # → <class 'int'>
|
|
type(3.14) # → <class 'float'>
|
|
type("Bonjour") # → <class 'str'>
|
|
type(True) # → <class 'bool'>
|
|
```
|
|
|
|
---
|
|
|
|
### 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)) # → <class 'int'>
|
|
|
|
x = "Bonjour" # x devient un str (la même variable change de type !)
|
|
print(type(x)) # → <class 'str'>
|
|
```
|
|
|
|
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)) # → <class 'int'>
|
|
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/)
|