Módulo 1 · Lección 14 de 59
La instrucción match
Comparar un valor contra varias alternativas concretas con match y case, y cuándo esto se lee mejor que una cadena de elif.
Hay un tipo de condición que aparece todo el tiempo: comparar una misma variable contra una lista de valores concretos. El número de una opción de menú, un código de error, el nombre de un comando. Con elif se puede, pero acabas repitiendo la variable en cada línea:
if opcion == "1":
...
elif opcion == "2":
...
elif opcion == "3":
...Desde la versión 3.10, Python tiene una instrucción específica para eso.
La forma básica#
opcion = "2"
match opcion:
case "1":
print("Has elegido: ver el saldo")
case "2":
print("Has elegido: hacer un ingreso")
case "3":
print("Has elegido: salir")
case _:
print("Opción no válida")Has elegido: hacer un ingresoLa estructura es esta:
matchseguido del valor que quieres examinar y dos puntos.- Uno o más
case, sangrados cuatro espacios, cada uno con el valor con el que comparar y sus propios dos puntos. - Dentro de cada
case, su bloque, a ocho espacios.
Igual que con elif, se evalúan en orden y solo se ejecuta el primero que encaja. No hace falta escribir nada para salir del match: cuando termina el bloque de un case, la instrucción entera acaba.
El comodín#
El caso case _: encaja con cualquier cosa, así que hace el papel del else. El guion bajo no es una variable: es un símbolo especial que significa "lo que sea, y no me interesa guardarlo".
Y como los case se evalúan en orden, el comodín tiene que ir el último. Python es tajante con esto:
El comodín es opcional. Si no lo pones y ningún caso encaja, no pasa nada: el match se salta entero, sin error.
opcion = "9"
match opcion:
case "1":
print("uno")
case "2":
print("dos")
print("Sigo aquí.")Sigo aquí.Igual que con los elif sin else, casi siempre querrás un case _: que al menos avise de que el valor no estaba previsto.
Varios valores en un mismo caso#
La barra vertical | agrupa alternativas en un solo case. Se lee como un "o":
dia = "sábado"
match dia:
case "sábado" | "domingo":
print("Fin de semana")
case "lunes" | "martes" | "miércoles" | "jueves" | "viernes":
print("Día laborable")
case _:
print("Eso no es un día de la semana")Fin de semanaCompara esa primera línea con su equivalente en elif, donde había que repetir dia == dos veces. Aquí es donde match gana de largo.
Funciona igual con números:
codigo = 404
match codigo:
case 200:
print("Correcto")
case 301 | 302:
print("Redirección")
case 404:
print("No encontrado")
case 500:
print("Error del servidor")
case _:
print(f"Código no contemplado: {codigo}")No encontradoGuardas con if#
Un case puede llevar una condición extra detrás, y entonces solo encaja si además se cumple:
nota = 9.5
match nota:
case _ if nota < 0 or nota > 10:
print("Nota fuera de rango")
case _ if nota >= 9:
print("Sobresaliente")
case _ if nota >= 7:
print("Notable")
case _:
print("Menos de un notable")SobresalienteEsa parte if ... se llama guarda. Fíjate en el detalle importante: para comparar por intervalos hay que poner el comodín en todos los casos, porque un rango no es un valor concreto con el que un patrón pueda coincidir.
Que funcione no significa que sea buena idea. Un match en el que todos los casos son case _ if, como este, es un if/elif disfrazado y más largo. Donde las guardas tienen sentido es cuando combinas valor concreto y condición:
codigo = 404
match codigo:
case 200:
print("Correcto")
case _ if 400 <= codigo < 500:
print("Error del cliente")
case _ if 500 <= codigo < 600:
print("Error del servidor")
case _:
print("Código desconocido")Error del clienteCapturar el valor#
Si en lugar de _ pones un nombre de variable, el case también encaja con todo, pero además guarda el valor en ese nombre:
comando = "borrar"
match comando:
case "listar":
print("Listando")
case otro:
print(f"No conozco el comando {otro}")No conozco el comando borrarEn este ejemplo no aporta nada, porque comando ya estaba en una variable. Pero esa regla explica un error que desconcierta mucho al empezar:
Cuándo usar match y cuándo no#
| Situación | Qué se lee mejor |
|---|---|
| Una variable contra varios valores fijos | match |
| Varios valores en el mismo caso | match, con la barra vertical |
Comparaciones por intervalos (>=, <) | if/elif |
| Condiciones sobre variables distintas en cada rama | if/elif |
| Solo dos casos | if/else |
En resumen: match para valores concretos, elif para condiciones. Y no te sientas obligado a usarlo. Una cadena de elif bien ordenada no es peor código; simplemente, cuando comparas la misma variable contra seis literales, match dice lo mismo con menos ruido.
Ejemplo completo#
print("CONVERSOR DE UNIDADES")
print("Unidades: km, m, cm")
valor = float(input("Valor: "))
unidad = input("Unidad de origen: ").strip().lower()
match unidad:
case "km":
metros = valor * 1000
case "m":
metros = valor
case "cm":
metros = valor / 100
case _:
metros = None
if metros is None:
print(f"No conozco la unidad '{unidad}'.")
else:
print(f"{'Metros:':<12}{metros:>12,.3f}")
print(f"{'Kilómetros:':<12}{metros / 1000:>12,.3f}")CONVERSOR DE UNIDADES
Unidades: km, m, cm
Valor: 1500
Unidad de origen: m
Metros: 1,500.000
Kilómetros: 1.500Fíjate en el uso de None como "no hay resultado" y en la comprobación posterior con is None, que es justo el caso en que se usa is en lugar de ==.