Acordeón de los Índices
Índice de los temas
Lección: 6 - Python Match, The Python Match Statement, Default Value, Combine Values, If Statements as Guards
Python Match
🐍 Python Match: Introducción a la Coincidencia de Patrones
La sentencia match
, introducida en Python 3.10, proporciona una forma elegante y legible de implementar lógica condicional basada en la estructura de un valor. Es similar a la sentencia switch
en otros lenguajes, pero con capacidades de coincidencia de patrones mucho más potentes.
En lugar de comparar un valor con múltiples constantes, match
permite comparar un valor con una serie de patrones. Estos patrones pueden incluir literales, variables, secuencias, diccionarios e incluso combinaciones más complejas.
¿Por qué usar `match`?
- Legibilidad mejorada: Para estructuras condicionales complejas que involucran la inspección de la forma de los datos,
match
puede ser mucho más claro y conciso que una larga cadena de sentenciasif-elif-else
. - Coincidencia de patrones estructurada: Permite verificar la estructura de los datos de una manera más directa y expresiva.
- Desempaquetado automático: Puede desempaquetar elementos de secuencias o diccionarios directamente en los patrones.
Sintaxis básica de `match`:
match valor:
case patron1:
# Código a ejecutar si valor coincide con patron1
instrucciones1
case patron2:
# Código a ejecutar si valor coincide con patron2
instrucciones2
case _:
# Código a ejecutar si valor no coincide con ningún patrón anterior (caso por defecto)
instrucciones_default
La sentencia match
toma una expresión (valor
) y la compara secuencialmente con cada uno de los patrones especificados en las cláusulas case
. Cuando se encuentra una coincidencia, se ejecuta el bloque de código correspondiente y la ejecución de la sentencia match
finaliza.
El último case
con el patrón _
actúa como un comodín o caso por defecto. Si ningún otro patrón coincide, se ejecuta el código asociado con _
.
Ejemplo introductorio:
http_status = 404
match http_status:
case 200:
print("OK")
case 404:
print("Not Found") # Output: Not Found
case 500:
print("Internal Server Error")
case _:
print("Código de estado desconocido")
En este ejemplo, el valor de http_status
se compara con cada uno de los patrones literales en las cláusulas case
. Cuando encuentra una coincidencia con 404
, se imprime "Not Found" y la sentencia match
termina.
The Python Match Statement
⚙️ El Funcionamiento de la Sentencia `match` en Python
La sentencia match
evalúa una expresión (el "sujeto") y la compara con una serie de patrones definidos en los bloques case
. La ejecución fluye al primer bloque case
cuyo patrón coincide con el sujeto. Dentro de un bloque case
, las variables pueden ser "capturadas" si el patrón lo especifica.
Patrones Literales:
Como vimos en el ejemplo introductorio, el patrón más simple es un literal (un número, una cadena, un booleano o None
). Un bloque case
con un patrón literal solo coincidirá si el sujeto es igual a ese literal (usando el operador ==
).
comando = "cerrar"
match comando:
case "abrir":
print("Abriendo...")
case "cerrar":
print("Cerrando...") # Output: Cerrando...
case "guardar":
print("Guardando...")
case _:
print("Comando desconocido.")
Patrones de Variables:
Si un patrón es un nombre de variable, siempre coincidirá con el sujeto y vinculará la variable al valor del sujeto. Esto es especialmente útil en el caso por defecto (case _
), donde queremos capturar el valor que no coincidió con ningún patrón anterior.
codigo_error = 503
match codigo_error:
case 200:
mensaje = "OK"
case 404:
mensaje = "No encontrado"
case error: # 'error' es una variable que capturará el valor si no hay coincidencia anterior
mensaje = f"Error desconocido: {error}" # Output: Error desconocido: 503
print(mensaje)
Nota: Si usas un nombre de variable en un case
que no es _
, Python asumirá que quieres capturar el valor en esa variable y siempre coincidirá. Para comparar con un valor que ya está en una variable, necesitas usar patrones de valor (que veremos más adelante).
Patrones de Secuencia:
Los patrones también pueden coincidir con la estructura de secuencias (listas, tuplas). Puedes especificar una longitud exacta o usar *
para coincidir con el resto de una secuencia.
punto = (10, 20)
match punto:
case (0, 0):
print("Origen")
case (x, 0):
print(f"En el eje x en x={x}")
case (0, y):
print(f"En el eje y en y={y}")
case (x, y):
print(f"Punto en x={x}, y={y}") # Output: Punto en x=10, y=20
case _:
print("No es un punto bidimensional")
coordenadas = [1, 2, 3, 4]
match coordenadas:
case [x, y]:
print(f"Dos coordenadas: {x}, {y}")
case [x, y, *resto]:
print(f"Al menos dos coordenadas: {x}, {y}, y el resto {resto}") # Output: Al menos dos coordenadas: 1, 2, y el resto [3, 4]
case _:
print("No es una lista de coordenadas")
Estos son solo algunos de los patrones básicos que puedes usar con la sentencia match
. En los siguientes temas, exploraremos patrones más avanzados.
Default Value
🧮 Valores por Defecto en Patrones `match`
Aunque la sentencia match
no tiene una sintaxis directa para definir valores por defecto dentro de los patrones de la misma manera que los argumentos de una función, el uso del patrón comodín _
al final de la estructura match
cumple una función similar. Actúa como un "caso por defecto" que se ejecuta si ninguno de los patrones anteriores coincide con el sujeto.
El Patrón Comodín `_` como Caso por Defecto:
El patrón _
siempre coincide y no vincula ningún nombre. Es la forma estándar de implementar un comportamiento por defecto en una sentencia match
, asegurando que siempre se ejecute un bloque de código, incluso si no hay coincidencias específicas.
operacion = "dividir"
match operacion:
case "sumar":
print("Realizando suma...")
case "restar":
print("Realizando resta...")
case "multiplicar":
print("Realizando multiplicación...")
case _:
print(f"Operación '{operacion}' no soportada.") # Output: Operación 'dividir' no soportada.
En este ejemplo, si la variable operacion
no coincide con ninguno de los casos específicos ("sumar", "restar", "multiplicar"), se ejecutará el bloque de código asociado con _
, proporcionando un mensaje por defecto.
Capturando el Valor por Defecto:
Si necesitas acceder al valor que no coincidió con ningún patrón específico en el caso por defecto, puedes usar un nombre de variable en lugar de _
. Como vimos en el tema anterior, una variable en un case
siempre coincide y captura el valor.
entrada = "comando_raro"
match entrada:
case "procesar":
print("Procesando...")
case "iniciar":
print("Iniciando...")
case desconocido:
print(f"Comando desconocido: '{desconocido}'.") # Output: Comando desconocido: 'comando_raro'.
Aquí, la variable desconocido
actuará como un "valor por defecto" capturando cualquier entrada que no sea "procesar" o "iniciar".
Consideraciones:
- Siempre es recomendable incluir un caso por defecto (ya sea con
_
o una variable) al final de tu sentenciamatch
para manejar situaciones inesperadas. - El orden de los casos es importante. Una vez que un patrón coincide, el bloque de código correspondiente se ejecuta y la sentencia
match
termina. Por lo tanto, el caso por defecto debe ir al final.
Aunque no hay una sintaxis explícita de "valor por defecto" dentro de los patrones individuales, el patrón comodín _
y la captura de variables en el último caso proporcionan mecanismos efectivos para manejar valores que no coinciden con ningún patrón específico.
Combine Values
🔗 Combinando Valores en Patrones `match`
La potencia de la sentencia match
radica en su capacidad para inspeccionar la estructura de los datos y combinar valores dentro de los patrones. Esto permite una lógica condicional más expresiva y concisa.
Tuplas y Listas Anidadas:
Puedes crear patrones que coincidan con tuplas o listas que contengan otros tuplas o listas, permitiendo una inspección profunda de la estructura de los datos.
datos = ("punto", (10, 20))
match datos:
case ("punto", (0, 0)):
print("Origen")
case ("punto", (x, y)):
print(f"Punto en x={x}, y={y}") # Output: Punto en x=10, y=20
case ("linea", (x1, y1), (x2, y2)):
print(f"Línea desde ({x1}, {y1}) hasta ({x2}, {y2})")
case _:
print("Formato desconocido")
elementos = [1, [2, 3], 4]
match elementos:
case [a, [b, c], d]:
print(f"a={a}, b={b}, c={c}, d={d}") # Output: a=1, b=2, c=3, d=4
case [primero, segundo, tercero]:
print(f"Tres elementos: {primero}, {segundo}, {tercero}")
case _:
print("Estructura de lista desconocida")
El Patrón OR (`|`):
Puedes usar el operador OR (|
) dentro de un patrón para especificar múltiples posibilidades. Si el sujeto coincide con cualquiera de los patrones separados por |
, se considera una coincidencia.
comando = "salir"
match comando:
case "cerrar" | "salir" | "fin":
print("Finalizando la aplicación.") # Output: Finalizando la aplicación.
case "ayuda" | "?":
print("Mostrando la ayuda...")
case otro_comando:
print(f"Comando '{otro_comando}' no reconocido.")
Patrones con Clases:
La sentencia match
también puede coincidir con instancias de clases, permitiendo inspeccionar los atributos de los objetos.
class Punto:
def __init__(self, x, y):
self.x = x
self.y = y
p = Punto(5, 10)
match p:
case Punto(x=0, y=0):
print("Origen")
case Punto(x=x, y=0):
print(f"En el eje x en x={x}")
case Punto(x=0, y=y):
print(f"En el eje y en y={y}")
case Punto(x=x, y=y) if x == y:
print(f"Punto en la diagonal x=y en ({x}, {y})")
case Punto(x=x, y=y):
print(f"Otro punto en x={x}, y={y}") # Output: Otro punto en x=5, y=10
case _:
print("No es un objeto Punto")
Nota: En los patrones de clase, puedes especificar los atributos por nombre (como x=x
, y=y
) para realizar la coincidencia basada en los valores de los atributos.
Combinar valores en los patrones `match` nos brinda una gran flexibilidad para analizar la estructura y el contenido de los datos de una manera muy clara y poderosa.
If Statements as Guards
🛡️ Sentencias `if` como Guardas en `match`
En la sentencia match
, puedes añadir una condición adicional a un case
utilizando la palabra clave if
. Esta condición se conoce como "guarda". Un bloque case
con una guarda solo se ejecutará si el patrón coincide con el sujeto y la expresión de la guarda es verdadera.
Sintaxis de las Guardas:
match valor:
case patron if condicion:
# Código a ejecutar si valor coincide con patron Y condicion es True
instrucciones
case otro_patron:
# Código a ejecutar si valor coincide con otro_patron
otras_instrucciones
case _:
# Código por defecto
instrucciones_default
La guarda se evalúa después de que el patrón ha coincidido. Si la guarda evalúa a False
, el intérprete de Python continúa buscando la siguiente coincidencia de patrón.
Ejemplos de Uso de Guardas:
punto = (3, 4)
match punto:
case (x, y) if x == y:
print(f"Punto en la diagonal x=y en ({x}, {y})")
case (x, y) if x > 0 and y > 0:
print(f"Punto en el primer cuadrante en ({x}, {y})") # Output: Punto en el primer cuadrante en (3, 4)
case (x, y):
print(f"Otro punto en ({x}, {y})")
case _:
print("No es un punto bidimensional")
codigo = ("error", 500)
match codigo:
case ("error", status) if 400 <= status < 500:
print(f"Error de cliente con código {status}")
case ("error", status) if 500 <= status < 600:
print(f"Error de servidor con código {status}") # Output: Error de servidor con código 500
case (tipo, valor):
print(f"Otro tipo de código: {tipo}, {valor}")
case _:
print("Código desconocido")
temperatura = 25
estado = "soleado"
match (estado, temperatura):
case ("lluvioso", temp) if temp < 15:
print("Frío y lluvioso")
case ("soleado", temp) if 20 <= temp < 30:
print("Agradable y soleado") # Output: Agradable y soleado
case (est, temp):
print(f"Estado: {est}, Temperatura: {temp}")
Beneficios de las Guardas:
- Lógica condicional más precisa: Permiten refinar la coincidencia de patrones basada en condiciones adicionales.
- Evitar anidamiento profundo: En algunos casos, las guardas pueden ayudar a evitar la necesidad de anidar sentencias `if` dentro de los bloques `case`, mejorando la legibilidad.
- Manejo de casos específicos: Son útiles para manejar casos particulares dentro de una estructura de patrón general.
Las guardas (`if` statements) en la sentencia match
son una herramienta poderosa para crear una lógica de coincidencia de patrones aún más sofisticada y específica.
0 Comentarios
Si desea contactar comigo, lo puede hacer atravez deste formulario gracias