
L'instruction match/case compare une valeur à une série de motifs (patterns) et exécute le premier bloc qui correspond. Introduite par Python 3.10 (PEP 634), elle ne se limite pas à tester une égalité comme le switch d'autres langages : elle déstructure la valeur, c'est-à-dire qu'elle inspecte sa forme (une liste de deux éléments, un dictionnaire avec telle clé, une instance de classe) et extrait les morceaux qui vous intéressent au passage. C'est le structural pattern matching. Ce guide couvre les motifs littéraux, la capture de variable, le wildcard _, les motifs de séquence et de mapping, les motifs de classe, l'opérateur | et les gardes.
Il s'adresse aux développeurs qui écrivent des cascades de if/elif à rallonge et cherchent une écriture plus lisible pour aiguiller sur la structure d'une donnée. Les exemples ont été exécutés avec Python 3.12.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Écrire une instruction
match/casede base avec le wildcard_. - Différencier un motif littéral d'un motif de capture.
- Déstructurer des séquences et des dictionnaires directement dans le
case. - Filtrer sur le type et les attributs d'un objet avec les motifs de classe.
- Combiner des motifs avec
|et affiner avec une gardeif. - Savoir quand
matchest plus clair qu'une cascade deif/elif.
L'instruction match/case de base
Section intitulée « L'instruction match/case de base »Une instruction match prend une valeur, puis la confronte à chaque case dans l'ordre. Le premier motif qui correspond gagne, et Python s'arrête là (pas de fallthrough, donc aucun break à écrire). Le motif spécial _, appelé wildcard, correspond à tout : il joue le rôle du cas par défaut.
def decrire_feu(couleur): match couleur: case "vert": return "Passez" case "orange": return "Ralentissez" case "rouge": return "Arretez-vous" case _: return "Couleur inconnue"
for c in ["vert", "orange", "rouge", "bleu"]: print(c, "->", decrire_feu(c))La sortie confirme que chaque couleur connue tombe sur son case, et que "bleu" termine sur le wildcard :
vert -> Passezorange -> Ralentissezrouge -> Arretez-vousbleu -> Couleur inconnueIci, les motifs "vert", "orange" et "rouge" sont des motifs littéraux : ils testent une égalité avec une constante. C'est le cas le plus simple, très proche d'un switch classique.
Le motif de capture
Section intitulée « Le motif de capture »Un motif de capture n'est pas une constante, mais un nom de variable. Il correspond toujours, et lie la valeur testée à ce nom pour que vous puissiez la réutiliser dans le bloc. C'est la grande différence avec un switch : le case ne fait pas que comparer, il extrait.
def message_statut(code): match code: case 200: return "OK" case 404: return "Page introuvable" case autre: return f"Code non gere : {autre}"
print(message_statut(200))print(message_statut(404))print(message_statut(500))Le troisième case autre attrape tout ce qui n'est ni 200 ni 404, et récupère la valeur dans autre :
OKPage introuvableCode non gere : 500Les motifs de séquence
Section intitulée « Les motifs de séquence »Un motif de séquence décrit la forme d'une liste ou d'un tuple : combien d'éléments, et comment les nommer. On l'écrit avec des crochets, comme une liste, mais chaque position est un sous-motif. L'étoile *reste capture « tout le reste » de la séquence, exactement comme le unpacking que vous connaissez déjà.
def analyser_commande(commande): match commande: case []: return "Aucune commande" case [action]: return f"Action seule : {action}" case [action, cible]: return f"{action} sur {cible}" case [action, *arguments]: return f"{action} avec {len(arguments)} arguments : {arguments}"
print(analyser_commande([]))print(analyser_commande(["lister"]))print(analyser_commande(["copier", "rapport.pdf"]))print(analyser_commande(["deployer", "web", "api", "cache"]))Chaque motif teste une longueur différente, et le dernier absorbe les arguments restants :
Aucune commandeAction seule : listercopier sur rapport.pdfdeployer avec 3 arguments : ['web', 'api', 'cache']Ce mécanisme brille pour router une commande ou décomposer une ligne déjà découpée. Notez que le motif teste la structure (le nombre d'éléments), pas seulement la valeur : c'est ce qui dépasse largement un switch.
Les motifs de mapping
Section intitulée « Les motifs de mapping »Un motif de mapping inspecte un dictionnaire par ses clés. Vous écrivez les clés qui vous intéressent et un sous-motif pour chaque valeur associée. Point important : le motif correspond même si le dictionnaire contient d'autres clés en plus. Il vérifie une présence, pas une égalité exacte.
def traiter_evenement(evenement): match evenement: case {"type": "connexion", "utilisateur": nom}: return f"Connexion de {nom}" case {"type": "erreur", "code": code}: return f"Erreur {code}" case {"type": type_inconnu}: return f"Evenement non gere : {type_inconnu}"
print(traiter_evenement({"type": "connexion", "utilisateur": "Alice"}))print(traiter_evenement({"type": "erreur", "code": 500, "detail": "timeout"}))print(traiter_evenement({"type": "deconnexion"}))Le deuxième appel correspond bien au motif erreur alors qu'il porte une clé detail supplémentaire, ignorée sans erreur :
Connexion de AliceErreur 500Evenement non gere : deconnexionCe motif est taillé pour les charges JSON et les événements typés par une clé "type". Vous testez la clé discriminante et capturez les champs utiles en une seule ligne, sans empiler des accès par index.
Les motifs de classe
Section intitulée « Les motifs de classe »Un motif de classe vérifie qu'une valeur est une instance d'une classe, tout en filtrant sur ses attributs. On écrit le nom de la classe suivi des attributs entre parenthèses, comme un appel de constructeur inversé. C'est particulièrement lisible avec une dataclass, dont les attributs sont explicites.
from dataclasses import dataclass
@dataclassclass Point: x: int y: int
def situer(point): match point: case Point(x=0, y=0): return "Origine" case Point(x=0, y=y): return f"Sur l'axe vertical a y={y}" case Point(x=x, y=0): return f"Sur l'axe horizontal a x={x}" case Point(x=x, y=y): return f"Point libre ({x}, {y})"
print(situer(Point(0, 0)))print(situer(Point(0, 5)))print(situer(Point(3, 0)))print(situer(Point(2, 7)))Chaque case combine une contrainte (x=0, motif littéral) et une capture (y=y, motif de capture) sur les attributs :
OrigineSur l'axe vertical a y=5Sur l'axe horizontal a x=3Point libre (2, 7)Ce motif s'appuie sur la programmation orientée objet : il faut une classe pour l'utiliser. Si les objets et les attributs sont encore flous, la POO en Python pose les bases nécessaires avant d'aller plus loin.
Combiner les motifs avec l'opérateur OU
Section intitulée « Combiner les motifs avec l'opérateur OU »L'opérateur | (le OU, ou or-pattern) regroupe plusieurs motifs dans un même case : il correspond si l'un d'eux correspond. Cela évite de dupliquer un bloc identique pour des valeurs qui déclenchent le même traitement.
def categorie_jour(jour): match jour: case "samedi" | "dimanche": return "Week-end" case "lundi" | "mardi" | "mercredi" | "jeudi" | "vendredi": return "Jour ouvre" case _: return "Jour invalide"
print(categorie_jour("samedi"))print(categorie_jour("mardi"))print(categorie_jour("nimportequoi"))Les deux jours du week-end partagent un seul bloc, tout comme les cinq jours ouvrés :
Week-endJour ouvreJour invalideLe | reste lisible tant que la liste ne s'allonge pas trop. Au-delà d'une poignée de valeurs, un simple test d'appartenance if jour in {...} redevient plus direct.
Affiner avec une garde
Section intitulée « Affiner avec une garde »Une garde est une condition if ajoutée après un motif. Le case ne correspond que si le motif et la condition sont vrais. La garde permet de tester ce qu'un motif seul ne peut pas exprimer : une comparaison (< 15), une relation entre variables (x == y), un appel de fonction.
def evaluer_temperature(mesure): match mesure: case temp if temp < 0: return f"{temp} degres : gel" case temp if temp < 15: return f"{temp} degres : froid" case temp if temp < 30: return f"{temp} degres : tempere" case temp: return f"{temp} degres : chaud"
print(evaluer_temperature(-5))print(evaluer_temperature(10))print(evaluer_temperature(22))print(evaluer_temperature(35))Chaque case capture la valeur dans temp, puis la garde décide de l'intervalle :
-5 degres : gel10 degres : froid22 degres : tempere35 degres : chaudLa garde se marie très bien avec un motif de classe pour tester une relation entre attributs, impossible à écrire dans le motif lui-même :
def livraison(point): match point: case Point(x=x, y=y) if x == y: return f"Sur la diagonale ({x}, {y})" case Point(x=x, y=y): return f"Hors diagonale ({x}, {y})"
print(livraison(Point(4, 4)))print(livraison(Point(4, 9)))Sur la diagonale (4, 4)Hors diagonale (4, 9)Quand préférer match à une cascade de if/elif
Section intitulée « Quand préférer match à une cascade de if/elif »match n'est pas un remplacement systématique de if/elif. Pour un test booléen simple ou une seule condition, un if reste plus court et plus clair. Le pattern matching gagne quand vous aiguillez sur la structure d'une donnée : une forme de liste, la présence de clés dans un dictionnaire, le type et les attributs d'un objet.
Comparez ces deux versions du routage de commande. En if/elif, la logique de longueur et d'extraction se répète à la main :
def analyser_if(commande): if len(commande) == 0: return "Aucune commande" elif len(commande) == 1: return f"Action seule : {commande[0]}" elif len(commande) == 2: return f"{commande[0]} sur {commande[1]}" else: return f"{commande[0]} avec {len(commande) - 1} arguments"La version match déclare la forme attendue et nomme les morceaux au même endroit, sans len() ni index répétés. L'intention se lit directement dans les motifs. Retenez la règle : structure et déstructuration penchent pour match ; condition unique penche pour if.
Contrôle de connaissances
Section intitulée « Contrôle de connaissances »Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Profil de compétences
Quoi faire maintenant
Ressources pour progresser
Des indices pour retenter votre chance ?
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications
À retenir
Section intitulée « À retenir »match/casecompare une valeur à des motifs et exécute le premier qui correspond, sansfallthrough.- Un motif littéral teste une égalité ; un nom nu est toujours une capture, jamais une comparaison.
- Le wildcard
_joue le rôle de cas par défaut et correspond à tout. - Les motifs de séquence (
[a, b, *reste]) déstructurent listes et tuples selon leur longueur. - Les motifs de mapping (
{"cle": valeur}) testent la présence de clés, en ignorant les clés en trop. - Les motifs de classe (
Point(x=0, y=y)) filtrent sur le type et les attributs d'un objet. - L'opérateur
|regroupe des motifs ; une gardeifajoute une condition que le motif seul ne peut pas exprimer. matchgagne sur la structure d'une donnée ;if/elifreste préférable pour une condition unique.- Fonctionnalité disponible depuis Python 3.10 uniquement.
Pour aller plus loin
Section intitulée « Pour aller plus loin »Le pattern matching prend toute sa valeur sur des données structurées reçues d'un fichier ou d'une API.
- Appeler une API avec requests : filtrer par motif les réponses structurées d'une API.