match-case en Python: guía de pattern matching

Publicado el: 11/07/2026
Tempo de leitura: 4 minutos
Pattern matching com match case em Python

La estructura match-case, disponible desde Python 3.10, permite comparar un valor con patrones estructurales. No es simplemente una versión de switch: además de comparar constantes, puede descomponer listas, tuplas, diccionarios y objetos, capturar partes del valor y aplicar condiciones adicionales. Utilizada correctamente, hace más legible el código que interpreta comandos, respuestas de APIs, eventos o estructuras de datos.

Antes de empezar conviene dominar las condiciones if, elif y else, las tuplas en Python, los conceptos de listas y las dataclasses. match-case resulta más útil cuando la forma de los datos importa tanto como su valor.

Sintaxis básica

def describir_estado(estado):
    match estado:
        case "pendiente":
            return "La tarea todavía no comenzó"
        case "procesando":
            return "La tarea está en curso"
        case "completado":
            return "La tarea terminó"
        case _:
            return "Estado desconocido"

El guion bajo representa cualquier valor que no coincidió anteriormente. Se recomienda colocarlo al final.

Comparar varios valores

El operador | permite agrupar alternativas:

def es_fin_de_semana(dia):
    match dia.lower():
        case "sábado" | "sabado" | "domingo":
            return True
        case _:
            return False

Esto evita repetir el mismo bloque para varios valores equivalentes.

Capturar el valor

def procesar_comando(comando):
    match comando:
        case "salir":
            return "Finalizando"
        case otro:
            return f"Comando recibido: {otro}"

Un nombre sin calificar captura cualquier valor. No se interpreta como una constante. Este detalle causa errores cuando un desarrollador espera comparar con una variable existente.

Patrones con secuencias

def interpretar_punto(punto):
    match punto:
        case [0, 0]:
            return "Origen"
        case [x, 0]:
            return f"Eje X en {x}"
        case [0, y]:
            return f"Eje Y en {y}"
        case [x, y]:
            return f"Punto ({x}, {y})"
        case _:
            return "Formato inválido"

El patrón acepta listas y tuplas compatibles con la longitud esperada. Las variables x e y reciben los elementos.

Capturar el resto de una secuencia

def analizar_ruta(partes):
    match partes:
        case ["usuarios", id_usuario]:
            return ("perfil", id_usuario)
        case ["usuarios", id_usuario, "pedidos", *resto]:
            return ("pedidos", id_usuario, resto)
        case _:
            return None

*resto captura los elementos restantes. Solo puede existir una captura con asterisco dentro del mismo patrón de secuencia.

Patrones con diccionarios

def manejar_evento(evento):
    match evento:
        case {"tipo": "login", "usuario": usuario}:
            return f"Inicio de sesión: {usuario}"
        case {"tipo": "compra", "id": id_compra, "total": total}:
            return f"Compra {id_compra}: {total}"
        case {"tipo": tipo}:
            return f"Evento no tratado: {tipo}"
        case _:
            return "Evento inválido"

El diccionario puede contener claves adicionales. El patrón exige únicamente las claves indicadas. Esto es útil para respuestas JSON de APIs.

Capturar claves adicionales

match evento:
    case {"tipo": "compra", "id": identificador, **extras}:
        print(identificador, extras)

**extras guarda las demás claves. Evita confiar en ellas sin validarlas.

Usar guards con if

Un guard añade una condición después de que el patrón coincide:

def clasificar_pago(pago):
    match pago:
        case {"moneda": "EUR", "total": total} if total > 1000:
            return "Revisión manual"
        case {"moneda": "EUR", "total": total} if total >= 0:
            return "Pago normal"
        case _:
            return "Pago inválido"

El guard se evalúa únicamente después de capturar total. Si es falso, Python continúa con el siguiente case.

Patrones de clase

from dataclasses import dataclass

@dataclass
class Punto:
    x: int
    y: int


def describir(punto):
    match punto:
        case Punto(0, 0):
            return "Origen"
        case Punto(x, 0):
            return f"Eje X: {x}"
        case Punto(x, y):
            return f"Punto: {x}, {y}"
        case _:
            return "No es un punto"

Las dataclasses definen automáticamente información que permite patrones posicionales. También puedes utilizar nombres:

case Punto(x=0, y=valor):
    print(valor)

Comparar constantes correctamente

Un nombre simple captura, no compara. Para constantes utiliza literales, enumeraciones o atributos calificados:

from enum import Enum

class Estado(Enum):
    ACTIVO = "activo"
    INACTIVO = "inactivo"

match estado:
    case Estado.ACTIVO:
        print("Activo")
    case Estado.INACTIVO:
        print("Inactivo")

Escribir case ACTIVO: capturaría el valor y podría hacer inalcanzables los casos siguientes.

Patrón as

as permite capturar el valor completo además de sus partes:

match respuesta:
    case {"estado": "ok", "datos": [primero, *resto]} as completa:
        print(primero, resto, completa)

Esto es útil para registrar la estructura completa después de validarla.

Ejemplo: comandos de terminal

def ejecutar(tokens):
    match tokens:
        case ["crear", nombre]:
            return crear(nombre)
        case ["eliminar", nombre, "--forzar"]:
            return eliminar(nombre, forzar=True)
        case ["listar"]:
            return listar()
        case ["buscar", *terminos] if terminos:
            return buscar(" ".join(terminos))
        case _:
            return "Uso inválido"

El patrón expresa claramente las formas aceptadas de la entrada.

Ejemplo: procesar respuestas de una API

def interpretar_respuesta(respuesta):
    match respuesta:
        case {"ok": True, "data": datos}:
            return datos
        case {"ok": False, "error": {"code": codigo, "message": mensaje}}:
            raise RuntimeError(f"{codigo}: {mensaje}")
        case _:
            raise ValueError("Respuesta inesperada")

Aunque el patrón valida la estructura mínima, todavía debes verificar tipos, rangos y contenido.

Orden de los casos

Los casos se prueban de arriba hacia abajo. Coloca los patrones específicos antes de los generales:

match valor:
    case [0, 0]:
        ...
    case [x, y]:
        ...
    case _:
        ...

Si el patrón general aparece primero, los casos específicos nunca se ejecutan.

match-case vs if-elif

Utiliza if-elif cuando comparas condiciones independientes, rangos o expresiones booleanas:

if edad < 0:
    ...
elif edad < 18:
    ...

Utiliza match-case cuando quieres describir formas de datos, descomponer estructuras o manejar varias variantes bien definidas. No reemplaces todas las condiciones solo porque la sintaxis es nueva.

Compatibilidad de versiones

match-case requiere Python 3.10 o superior. Comprueba la versión:

python --version

Si el proyecto debe funcionar en Python 3.9, utiliza if-elif, diccionarios de funciones u otras estrategias.

Documentación y especificación

La documentación oficial sobre sentencias match incluye ejemplos con secuencias, clases y guards. La especificación formal está en la PEP 634 sobre structural pattern matching.

Pruebas recomendadas

Prueba cada forma aceptada y varios valores inválidos. Incluye diccionarios sin claves, secuencias con longitudes incorrectas, tipos inesperados, guards falsos y casos generales. Las pruebas ayudan a detectar cambios cuando una API añade nuevas variantes.

Errores frecuentes

Los problemas más comunes son confundir una captura con una constante, colocar un patrón general antes de uno específico, usar match-case en una versión antigua, asumir que un patrón de diccionario rechaza claves adicionales y olvidar validar los tipos capturados. También debes evitar bloques demasiado grandes: delega el trabajo a funciones.

Conclusión

match-case permite expresar patrones estructurales de forma clara. Puede comparar literales, descomponer secuencias, leer claves de diccionarios, reconocer objetos y aplicar guards. Su mayor ventaja aparece al interpretar datos con varias formas conocidas. Cuando solo necesitas una condición booleana sencilla, if-elif sigue siendo más directo. Utiliza la herramienta que comunique mejor la estructura y mantén los casos pequeños, ordenados y cubiertos por pruebas.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Uso de map e filter para agilizar código Python
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    map() y filter() en Python: guía práctica y eficiente

    Aprende map() y filter() en Python: transformación, filtrado, evaluación perezosa, pipelines, lambdas, errores y comparación con comprehensions.

    Ler mais

    Tempo de leitura: 5 minutos
    11/07/2026
    Comparação entre list comprehension e generator expression em Python
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    List comprehension vs generator expression en Python

    Compara list comprehension y generator expression en Python: memoria, evaluación perezosa, rendimiento, reutilización y casos prácticos.

    Ler mais

    Tempo de leitura: 5 minutos
    11/07/2026
    Logo do Python com as palavras global e local
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    Alcance de variables en Python: entiende la regla LEGB

    Entiende el alcance de variables en Python con la regla LEGB, global, nonlocal, closures, sombreado, mutabilidad y UnboundLocalError.

    Ler mais

    Tempo de leitura: 5 minutos
    11/07/2026
    Operações matemáticas usando o módulo math em Python
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    Módulo math en Python: operaciones matemáticas esenciales

    Aprende el módulo math en Python: raíces, potencias, redondeos, trigonometría, logaritmos, constantes, isclose y ejemplos prácticos.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026
    Geração de números aleatórios seguros usando secrets em Python
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    Módulo secrets en Python: números y tokens seguros

    Aprende secrets en Python para generar contraseñas, códigos y tokens seguros con randbelow, choice, token_hex, token_urlsafe y compare_digest.

    Ler mais

    Tempo de leitura: 5 minutos
    11/07/2026
    Uso do operador walrus para atribuições inline em Python
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    Operador walrus en Python: guía con ejemplos

    Aprende el operador walrus := en Python: condiciones, while, comprensiones, lectura por bloques, regex, alcance y buenas prácticas.

    Ler mais

    Tempo de leitura: 5 minutos
    11/07/2026