Apprenez en lisant dans l'ordre

enum et dataclasses — Constantes nommées et classes de données

Remplacer les littéraux chaîne par Enum, numéroter automatiquement avec IntEnum + auto() et trier, générer le code répétitif via @dataclass, et utiliser field(default_factory=list).

Deux modules pour rendre explicite le sens des valeurs. enum te permet de remplacer les littéraux chaîne dispersés dans ton code par des constantes nommées, donc les fautes de frappe surfacent à l'exécution au lieu de passer en silence. dataclasses fournit un moyen de définir une "classe qui ne fait que contenir des données" en une ligne, en éliminant le code répétitif de __init__ / __eq__ / __repr__.

Enum — remplacer les littéraux chaîne par des constantes nommées

Quand des littéraux chaîne comme "paid" / "shipped" sont dispersés dans ton code, les fautes de frappe comme "shippped" passent inaperçues jusqu'à l'exécution, l'autocomplétion n'aide pas, et les refactorisations sont fragiles. Enum résout ça en définissant l'ensemble des constantes comme une classe — les noms que tu définis s'autocomplètent dans ton éditeur, les fautes de frappe lèvent immédiatement AttributeError, l'itération sur tous les membres marche d'office, et tu obtiens une valeur sûre à utiliser comme clé de dict ou étiquette de switch.

# Chaînes de statut dispersées dans le code
if status == "paid":
    ship_order(order_id)
elif status == "shippped":   # Faute de frappe — devrait être "shipped", mais tu ne le remarqueras qu'à l'exécution
    notify_shipped(order_id)
elif status == "cancelled":
    refund(order_id)
Littéraux chaîne vs Enum
if status == "paid":(littéral chaîne)Faute "paied"ne lève aucune exception→ Bug reste cachéif status == OrderStatus.PAID:(Enum)OrderStatus.PAEID→ AttributeError→ Détecté immédiatement
Les chaînes brutes ne s'autocomplètent pas et les fautes de frappe passent jusqu'à l'exécution. Enum n'autorise que les noms que tu as définis, donc tu obtiens autocomplétion, détection de fautes, et itération complète des membres d'un coup.
from enum import Enum

class OrderStatus(Enum):
    PENDING = "pending"
    PAID = "paid"
    SHIPPED = "shipped"
    CANCELLED = "cancelled"

# Accès aux membres : chaque membre porte un nom et une valeur
print(OrderStatus.PAID)            # OrderStatus.PAID
print(OrderStatus.PAID.name)       # 'PAID'
print(OrderStatus.PAID.value)      # 'paid'

# Compare avec ==
status = OrderStatus.PAID
if status == OrderStatus.PAID:
    print("Paiement reçu")

Définis un statut de commande comme Enum et lis les infos des membres.

① Importe Enum depuis le module enum

② Définis une classe Enum OrderStatus avec les quatre membres PENDING / PAID / SHIPPED / CANCELLED (les valeurs sont les chaînes en minuscules "pending" / "paid" / "shipped" / "cancelled")

③ Affiche OrderStatus.PAID.name sous la forme PAID name : ◯◯

④ Affiche OrderStatus.PAID.value sous la forme PAID value : ◯◯

⑤ Affiche tous les noms de membres sous la forme Tous les membres : ◯ (tu peux itérer avec for s in OrderStatus)

(Si ton code s'exécute correctement, l'explication apparaîtra.)

Éditeur Python

Exécuter le code pour voir le résultat

Construis une fonction qui compare des membres d'Enum dans if/elif et retourne un message par statut. Brancher sur l'égalité membre à membre au lieu de littéraux chaîne est la façon la plus sûre de l'écrire.

① Définis OrderStatus de la Pratique 1

② Définis une fonction get_message(status) qui utilise if/elif sur chaque membre pour retourner : PENDING → "En attente de paiement", PAID → "Préparation de l'expédition", SHIPPED → "Expédié", CANCELLED → "Annulé"

③ Affiche get_message(OrderStatus.PAID) sous la forme PAID : ◯

④ Affiche get_message(OrderStatus.SHIPPED) sous la forme SHIPPED : ◯

Éditeur Python

Exécuter le code pour voir le résultat

IntEnum et auto — numérotation automatique et comparaison numérique

IntEnum est un Enum qui hérite de int, donc les membres se comparent et opèrent arithmétiquement comme des entiers. C'est le bon choix pour les constantes où l'ordre numérique compte — priorités, niveaux, rangs. auto() est une fonction qui assigne les valeurs automatiquement à la place de les écrire à la main : aligne des appels auto() et ils deviennent 1, 2, 3, 4... dans l'ordre de définition.

Quand les nombres spécifiques n'importent pas (seul l'ordre compte), auto() est plus sûr parce que ajouter ou retirer des membres n'oblige pas à réécrire les nombres à la main.

IntEnum + auto
class Priority(IntEnum): LOW = auto() MEDIUM = auto()auto() numérote auto1, 2, 3Priority.LOW < Priority.HIGH→ True (compare int)
auto() numérote automatiquement 1, 2, 3, .... IntEnum se compare avec int, donc Priority.LOW < Priority.HIGH fonctionne — l'ordre numérique encode la priorité.

Définis un IntEnum Priority avec auto() et trie plusieurs tâches de la priorité haute à la basse. Confirme dans un scénario réel que auto() numérote automatiquement et que IntEnum peut comparer et trier comme int.

① Importe IntEnum et auto depuis enum

② Définis une classe IntEnum Priority avec quatre membres LOW / MEDIUM / HIGH / URGENT (valeurs toutes en auto())

③ Construis une liste de toutes les valeurs de membres et affiche sous la forme Numérotation : ◯ (en confirmant que auto() a assigné 1, 2, 3, 4)

④ Trie la liste de tâches [("Nettoyage", Priority.LOW), ("Réponses email", Priority.HIGH), ("Préparer les documents", Priority.URGENT), ("Révision", Priority.MEDIUM)] de la priorité haute à la basse, puis sous le titre Ordre d'exécution : affiche chaque tâche sous la forme - nom (priorité)

Éditeur Python

Exécuter le code pour voir le résultat

@dataclass — définir une classe contenant des données en une ligne

Écrire une "classe simple avec juste des champs" à la main signifie définir __init__ pour fixer les attributs, __eq__ (la méthode dunder appelée pour les comparaisons ==) pour l'égalité de contenu, __repr__ (la méthode dunder appelée par print et le REPL) pour un affichage lisible, et ainsi de suite — les mêmes motifs répétitifs alignés à chaque fois. Un seul décorateur @dataclass génère tout ça automatiquement à partir de tes déclarations de champs annotés en type.

En d'autres termes, aligner simplement des attributs annotés en type construit toute la classe — tu obtiens les mêmes fonctionnalités pour beaucoup moins de code que les classes écrites à la main.

Ce que @dataclass génère automatiquement
@dataclassclass Order: id: int customer: str→ Auto-généré__init__Initialise les attributs__eq__== si tous les champs égaux__repr__Order(id=..., customer=...)
Il suffit de déclarer des champs annotés en type et tu obtiens __init__ / __eq__ / __repr__ gratuitement. field(default_factory=list) te permet de fixer en sécurité des valeurs par défaut mutables comme une liste vide, et frozen=True rend la classe immuable (changements d'attributs bloqués).

Utilise default_factory pour les valeurs par défaut mutables

Essayer de mettre une liste par défaut avec @dataclass en écrivant items: list = [] lève une SyntaxError (ou un avertissement de dépréciation). C'est une protection contre le bug classique de "chaque instance finit par partager la même liste". Utilise plutôt field(default_factory=list), qui crée une nouvelle liste vide par instance, ce qui est sûr. Même idée pour dict / set : field(default_factory=dict).

Définis un Order avec @dataclass et confirme les __eq__ et __repr__ auto-générés.

① Importe dataclass et field depuis dataclasses

② Définis une classe Order décorée par @dataclass — quatre champs : id: int, customer: str, items: list = field(default_factory=list), is_paid: bool = False

③ Construis une instance avec Order(id=1234, customer="Alice", items=["apple", "banana"]) et affiche-la directement (le __repr__ auto-généré s'active)

④ Construis une seconde instance avec le même contenu et affiche le résultat de la comparaison avec == sous la forme Égal : True / False

⑤ Change is_paid de la première instance à True, puis compare à nouveau avec == et affiche sous la forme Égal après changement : True / False

Éditeur Python

Exécuter le code pour voir le résultat
QUIZ

Vérification des connaissances

Répondez à chaque question une par une.

Question 1Quel est l'avantage de remplacer la comparaison de littéral chaîne "paid" par un Enum ?

Question 2Quel est l'avantage de auto() dans IntEnum ?

Question 3Quelle est la bonne façon de mettre une liste par défaut sur un champ dans @dataclass ?