El mecanismo de coincidencia de patrones apareció en Python 3.10 bajo el nombre de Structural Pattern Matching y se implementó a través de la construcción match-case. Esta herramienta permite analizar elegantemente y de manera concisa estructuras de datos complejas, comparándolas con patrones.
En muchos lenguajes funcionales (por ejemplo, en Haskell, Scala), la coincidencia de patrones se considera desde hace tiempo una forma conveniente de ramificar la lógica según la estructura de los datos. Python no contaba con este mecanismo durante mucho tiempo, utilizando en su lugar cadenas de if-elif-else o desestructuración.
Las estructuras de datos complejas y anidadas (diccionarios, listas, objetos) a menudo requieren múltiples comprobaciones de tipos, valores y estructuras, lo que lleva a un código confuso con muchas condiciones.
match-case ofrece una forma declarativa y legible de describir diferentes escenarios de procesamiento de datos teniendo en cuenta el tipo y la estructura sin sobrecargarlo de condiciones.
def process(event): match event: case {"type": "click", "x": x, "y": y}: return f"Click en ({x}, {y})" case [command, *args]: return f"Comando: {command}, args: {args}" case _: return "Evento desconocido" print(process({"type": "click", "x": 2, "y": 5})) # Click en (2, 5) print(process(["RUN", 1, 2, 3])) # Comando: RUN, args: [1, 2, 3]
¿Coincide match-case únicamente por valor? No. La coincidencia puede ocurrir por estructura, tipo, desestructuración de colecciones e incluso propiedades de objetos (si se especifican métodos especiales match_args).
¿Influye el orden de case en match? Sí. El análisis se realiza de arriba hacia abajo, el primer patrón adecuado se activa. Los siguientes case no se verifican.
¿Se pueden coincidir clases personalizadas? Sí, si la clase implementa los métodos match_args y/o getitem. Entonces la coincidencia de patrones podrá extraer valores de los campos.
class Point: __match_args__ = ("x", "y") def __init__(self, x, y): self.x = x self.y = y def where(obj): match obj: case Point(x, y): return f"Punto en {x}, {y}" case _: return "Desconocido" print(where(Point(1, 2))) # Punto en 1, 2
Pros:
Caso negativo: Los desarrolladores utilizaron match-case incluso para ramificaciones booleanas simples, lo que solo complicó el código. Pros: aprendieron una nueva característica. Contras: perdieron legibilidad y aumentaron la cantidad de errores.
Caso positivo: En una aplicación con un gran número de eventos y estructuras anidadas (por ejemplo, un analizador de gráficos), match-case permitió evitar largas cadenas de if-elif y centralizar el análisis. Pros: aumentó la legibilidad, redujo la cantidad de errores. Contras: se requirió capacitación del equipo para trabajar con la nueva construcción.