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
utilizamatch
para comparar el valor dedato
con los patrones definidos en los bloquescase
- 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
.