Cours Match Case Python
Cours Match Case Python
case en Python
1. Introduction et Définition
La structure match ... case est une instruction de pattern matching (filtrage
par motifs) introduite en Python 3.10 (PEP 634, 635, 636). Elle permet de
comparer une valeur contre une série de motifs et d’exécuter du code lorsqu’un
motif correspond.
Différence clé avec if/elif/else : match ... case peut déstructurer (extraire
les parties) des structures de données complexes (listes, dictionnaires, objets)
en une seule opération, là où if nécessiterait plusieurs vérifications manuelles.
2. Syntaxe de Base
match expression:
case pattern_1:
# bloc exécuté si pattern_1 correspond
case pattern_2:
# bloc exécuté si pattern_2 correspond
case _:
# bloc par défaut (wildcard, optionnel)
print(decrire_jour(2)) # Mardi
print(decrire_jour(9)) # Numéro invalide
match point:
case (0, 0):
print("Origine")
case (x, 0): # x capture la valeur, 0 est un littéral
print(f"Sur l'axe X à x={x}")
case (0, y):
print(f"Sur l'axe Y à y={y}")
case (x, y):
print(f"Point ({x}, {y})")
case _:
print("Format invalide")
match utilisateur:
case {"nom": str(nom), "age": int(age)}:
# Correspond si les clés "nom" et "age" existent et sont des st
r/int
print(f"{nom} a {age} ans")
case {"nom": nom}:
# Correspond si seule la clé "nom" existe
print(f"Nom connu : {nom}")
case {}:
print("Dictionnaire vide")
case _:
print("Ce n'est pas un dictionnaire")
@dataclass
class Point:
x: int
y: int
@dataclass
class Cercle:
centre: Point
rayon: float
match forme:
case Cercle(Point(0, 0), rayon):
print(f"Cercle centré à l'origine, rayon={rayon}")
case Cercle(centre, rayon):
print(f"Cercle en {centre}, rayon={rayon}")
case _:
print("Forme inconnue")
match commande:
case {
"type": "paiement",
"data": {
"montant": float(m),
"devise": "EUR",
"carte": {"numero": str(n)}
}
} if m > 0:
print(f"Paiement de {m} EUR par carte finissant par {n[-4:]}")
case _:
print("Commande invalide")
print(calculer(10, 3, "*")) # 30
print(calculer(10, 0, "/")) # Erreur
@dataclass
class Nombre:
valeur: int
@dataclass
class Addition:
gauche: 'Expression'
droite: 'Expression'
@dataclass
class Multiplication:
gauche: 'Expression'
droite: 'Expression'
# Test : (1 + 2) * 3
expr = Multiplication(Addition(Nombre(1), Nombre(2)), Nombre(3))
print(evaluer(expr)) # 9
5. Exercices
Exercice 1 : Niveau Débutant
Écrire une fonction decrire_animal(animal: str) qui retourne : - “Domestique”
pour “chat” ou “chien” - “Ferme” pour “vache”, “mouton”, “poule” - “Sauvage” pour
“lion”, “tigre”, “ours” - “Inconnu” sinon
# Votre code ici
def decrire_animal(animal: str) -> str:
...
Solution :
def decrire_animal(animal: str) -> str:
match animal:
case "chat" | "chien":
return "Domestique"
case "vache" | "mouton" | "poule":
return "Ferme"
case "lion" | "tigre" | "ours":
return "Sauvage"
case _:
return "Inconnu"
# Tests
print(decrire_animal("chat")) # Domestique
print(decrire_animal("poule")) # Ferme
print(decrire_animal("requin")) # Inconnu
Exercice 2 : Niveau Intermédiaire
Écrire une fonction analyser_coordonnees(point) qui prend un tuple de 2 ou 3
éléments : - (0, 0) → “Origine 2D” - (x, 0) → “Sur l’axe X en 2D” - (0, y) →
“Sur l’axe Y en 2D” - (x, y) → “Point 2D standard” - (x, y, z) → “Point 3D” -
Autre → “Format non supporté”
def analyser_coordonnees(point):
...
Solution :
def analyser_coordonnees(point):
match point:
case (0, 0):
return "Origine 2D"
case (x, 0):
return f"Sur l'axe X en 2D, x={x}"
case (0, y):
return f"Sur l'axe Y en 2D, y={y}"
case (x, y) if isinstance(x, (int, float)) and isinstance(y, (i
nt, float)):
return f"Point 2D ({x}, {y})"
case (x, y, z):
return f"Point 3D ({x}, {y}, {z})"
case _:
return "Format non supporté"
# Tests
print(analyser_coordonnees((0, 0))) # Origine 2D
print(analyser_coordonnees((5, 0))) # Sur l'axe X
print(analyser_coordonnees((1, 2, 3))) # Point 3D
print(analyser_coordonnees((1,))) # Format non supporté
Opérations supportées : "add", "sub", "mul", "div". Les opérandes peuvent être
des nombres ou des sous-expressions.
def evaluer_expression(expr):
...
Solution :
def evaluer_expression(expr):
match expr:
case {"op": "add", "left": left, "right": right}:
return evaluer_expression(left) + evaluer_expression(right)
case {"op": "sub", "left": left, "right": right}:
return evaluer_expression(left) - evaluer_expression(right)
case {"op": "mul", "left": left, "right": right}:
return evaluer_expression(left) * evaluer_expression(right)
case {"op": "div", "left": left, "right": right}:
r = evaluer_expression(right)
if r == 0:
raise ValueError("Division par zéro")
return evaluer_expression(left) / r
case int(n) | float(n):
return n
case _:
raise ValueError(f"Expression invalide : {expr}")
# Test
expr = {
"op": "add",
"left": 5,
"right": {
"op": "mul",
"left": 2,
"right": 3
}
}
print(evaluer_expression(expr)) # 11
expr2 = {
"op": "sub",
"left": {"op": "mul", "left": 4, "right": 5},
"right": 10
}
print(evaluer_expression(expr2)) # 10
Solution :
def valider_config(config: dict) -> str:
match config:
case {
"host": str(host),
"port": int(port),
**reste
} if not (1 <= port <= 65535):
return f"Invalide : port {port} hors range [1-65535]"
case {
"host": str(host),
"port": int(port),
"database": {"type": str(db_type), "name": str(db_name)},
**reste
} if db_type not in ("mysql", "postgres"):
return f"Invalide : type de BDD '{db_type}' non supporté"
case {
"host": str(host),
"port": int(port),
"database": {"type": str(db_type), "name": str(db_name)},
"debug": True,
**reste
}:
return f"Avertissement : mode debug activé pour {host}:{por
t} avec {db_type}/{db_name}"
case {
"host": str(host),
"port": int(port),
"database": {"type": str(db_type), "name": str(db_name)},
**reste
}:
return "Valide"
case {
"host": str(host),
"port": int(port),
"debug": True,
**reste
}:
return f"Avertissement : mode debug activé pour {host}:{por
t}"
case {
"host": str(host),
"port": int(port),
**reste
}:
return "Valide"
case _:
return "Invalide : configuration mal formée"
# Tests
cfg1 = {"host": "localhost", "port": 8080}
print(valider_config(cfg1)) # Valide
7. Récapitulatif Visuel
match donnée: # ← Expression à tester
case [1, 2, 3]: # ← Littéral séquence
...
case [tete, *queue]: # ← Séquence + capture
...
case {"status": 200, "body": b}: # ← Mapping
...
case Point(x=0, y=0): # ← Classe + args nommés
...
case n if n < 0: # ← Variable + guard
...
case _: # ← Joker (default)
...