pattern-matching-python

Pattern Matching en Python

El pattern matching es una técnica introducida en Python 3.10 que permite comparar una estructura de datos con un patrón dado y ejecutar código basado en la coincidencia de patrones.

A diferencia de las tradicionales sentencias if-else, el pattern matching proporciona una forma más legible y concisa de manejar diferentes casos, (especialmente cuando se trabaja con estructuras de datos anidadas y complejas).

Sintaxis del Pattern Matching

La sintaxis básica del pattern matching en Python se compone de la palabra clave match seguida de una expresión que se desea comparar, y un bloque case para definir los patrones a coincidir.

Vamos a ver un ejemplo básico de pattern matching utilizando una estructura de datos simple:

def analizar_dato(dato):
    match dato:
        case 1:
            return "Uno"
        case 2:
            return "Dos"
        case 3:
            return "Tres"
        case _:
            return "Otro valor"

En este ejemplo

  • La función analizar_dato utiliza match para comparar el valor de dato con los patrones definidos en los bloques case
  • Si dato es igual a 1, 2, o 3, se devuelve el texto correspondiente
  • De lo contrario, se devuelve “Otro valor”.

Coincidencia con estructuras de datos

El pattern matching en Python es especialmente útil cuando se utiliza con estructuras de datos más complejas (como listas, diccionarios y tuplas). Veamos algunos ejemplos más avanzados.

Listas y tuplas

En este ejemplo, vamos a ver cómo reconoces patrones en listas o en tuplas con Pattern Matching

def analizar_lista(lista):
    match lista:
        case [1, 2, 3]:
            return "Caso 1: 1 a 3"
        case [1, *resto]:
            return f"Caso 2: Empieza con 1 y luego {resto}"
        case _:
            return "Otro tipo de lista"

print(analizar_lista([1, 2, 3]))  # Salida: 'Caso 1: 1 a 3'
print(analizar_lista([1, 4, 5]))  # Salida: 'Empieza con 1 y luego [4, 5]'
print(analizar_lista([7, 8]))     # Salida: 'Otro tipo de lista'

En este ejemplo,

  • El patrón [1, 2, 3] busca exactamente esa lista
  • El patrón [1, *resto] utiliza el operador * para capturar todos los elementos restantes en una lista después de un elemento específico (en este caso, 1)
  • El patrón _ es un “descarte”, y se emplea para hacer un caso predeterminado si no se cumple ninguno de los anteriores

Diccionarios

También podemos aplicar Pattern Matching a diccionarios, para buscar los que cumplen alguna condición. Por ejemplo,

def analizar_diccionario(diccionario):
    match diccionario:
        case {"nombre": nombre, "edad": edad}:
            return f"Caso 1: Nombre: {nombre}, Edad: {edad}"
        case {"nombre": nombre}:
            return f"Caso 2: Nombre: {nombre}"
        case _:
            return "Otro tipo de diccionario"

print(analizar_diccionario({"nombre": "Ana", "edad": 30}))
# Salida: 'Caso 1: Nombre: Ana, Edad: 30'

print(analizar_diccionario({"nombre": "Luis"}))
# Salida: 'Caso 2: Nombre: Luis'
print(analizar_diccionario({"ciudad": "Madrid"}))
# Salida: Otro tipo de diccionario

Aquí, el patrón {"nombre": nombre, "edad": edad} se utiliza para coincidir con un diccionario que contiene claves específicas y capturar sus valores.

Patrones de clase

El pattern matching también permite trabajar con objetos de clase y verificar si una instancia de clase coincide con un patrón determinado:

class Persona:
    def __init__(self, nombre, edad):
        self.nombre = nombre
        self.edad = edad

def analizar_persona(persona):
    match persona:
        case Persona(nombre="Ana", edad=30):
            return "Persona Ana de 30 años"
        case Persona(nombre, edad):
            return f"Persona: {nombre}, Edad: {edad}"
        case _:
            return "Otro tipo de objeto"

persona1 = Persona("Ana", 30)
persona2 = Persona("Luis", 25)

print(analizar_persona(persona1))  # Salida: Persona Ana de 30 años
print(analizar_persona(persona2))  # Salida: Persona: Luis, Edad: 25

En este caso, se utiliza match para verificar instancias de la clase Persona y capturar los atributos nombre y edad.