Pattern Matching Structural în Python (match … case) în Python

Structuri de control Python 3.10+

Ghid complet pentru Structural Pattern Matching introdus în Python 3.10 (PEP 634): deconstrucția secvențelor, dicționarelor și obiectelor cu clauze de gardă și wildcards.

Sintaxă
match comanda:
    case ['muta', x, y] if x > 0:
        ...
    case {'tip': 'eroare', 'mesaj': m}:
        ...
    case _:
        ...

Introdus în Python 3.10 prin PEP 634, Structural Pattern Matching (instrucțiunea match ... case) este mult mai mult decât un simplu switch / case întâlnit în C sau JavaScript. Pe lângă testarea egalității simple, el realizează deconstrucția structurală a datelor (destructuring), potrivind forme complexe de tupluri, liste, dicționare și instanțe de clase, extrăgând automat valorile relevante în variabile locale.

Exemplu practic: Parsarea comenzilor primite dintr-un protocol de rețea
def proceseaza_actiune(comanda):
    match comanda:
        # Potrivire exactă de comandă fără parametri:
        case "iesire" | "quit":
            print("Sistem oprit.")
            
        # Deconstrucție de secvență cu lungime fixă și clauză de gardă (guard if):
        case ["muta", directie, distanta] if distanta > 0:
            print(f"Deplasare în direcția {directie} cu {distanta} metri.")
            
        # Potrivire de comenzi cu număr variabil de parametri (rest unpacking):
        case ["notifica", utilizator, *mesaje]:
            print(f"Trimitere către {utilizator}: {' '.join(mesaje)}")
            
        # Deconstrucție de dicționar: extrage valorile cheilor specificate
        case {"status": "eroare", "cod": cod, "detalii": detalii}:
            print(f"Alertă [Cod {cod}]: {detalii}")
            
        # Cazul implicit (Wildcard pattern):
        case _:
            print(f"Comandă necunoscută sau invalidă: {comanda!r}")

# Testare:
proceseaza_actiune(["muta", "nord", 25])
proceseaza_actiune({"status": "eroare", "cod": 404, "detalii": "Fișier negăsit"})
proceseaza_actiune(["notifica", "dan", "Serverul", "a", "fost", "repornit."])

Deconstrucția Instanțelor de Clase

Pattern matching-ul poate inspecta atributele claselor standard sau ale claselor @dataclass:

Potrivirea obiectelor prin pattern de clasă
from dataclasses import dataclass

@dataclass
class Punct:
    x: float
    y: float

def localizeaza_punct(punct):
    match punct:
        case Punct(x=0, y=0):
            print("Punctul se află exact în originea (0, 0).")
        case Punct(x=0, y=y):
            print(f"Punctul se află pe axa Y la cota {y}.")
        case Punct(x=x, y=0):
            print(f"Punctul se află pe axa X la poziția {x}.")
        case Punct(x=x, y=y) if x == y:
            print(f"Punctul se află pe prima bisectoare la ({x}, {y}).")
        case Punct(x=x, y=y):
            print(f"Punct oarecare la coordonatele ({x}, {y}).")

Capcane Frecvente de Evitat

  • Numele de variabile captează valori: Dacă scrieți case status:, Python nu compară cu variabila status din exterior, ci creează o nouă variabilă locală care capturează orice valoare! Pentru a compara cu o constantă definită anterior, folosiți notația cu punct: case Moduri.ACTIV:.
  • Dicționarele sunt potriviri parțiale: Spre deosebire de liste (unde lungimea trebuie să se potrivească exact), case {"status": "ok"}: se potrivește chiar dacă dicționarul analizat are și alte chei suplimentare.