Saltar al contenido
🐍 Curso de Python
/

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.

⏱ 9 min de lectura

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:

python
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#

python
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")
Salida en pantalla
Has elegido: hacer un ingreso

La estructura es esta:

  • match seguido 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.

python
opcion = "9"

match opcion:
        case "1":
                print("uno")
    case "2":
                print("dos")

print("Sigo aquí.")
Salida en pantalla
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":

python
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")
Salida en pantalla
Fin de semana

Compara 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:

python
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}")
Salida en pantalla
No encontrado

Guardas con if#

Un case puede llevar una condición extra detrás, y entonces solo encaja si además se cumple:

python
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")
Salida en pantalla
Sobresaliente

Esa 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:

python
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")
Salida en pantalla
Error del cliente

Capturar 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:

python
comando = "borrar"

match comando:
        case "listar":
                print("Listando")
    case otro:
                print(f"No conozco el comando {otro}")
Salida en pantalla
No conozco el comando borrar

En 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ónQué se lee mejor
Una variable contra varios valores fijosmatch
Varios valores en el mismo casomatch, con la barra vertical
Comparaciones por intervalos (>=, <)if/elif
Condiciones sobre variables distintas en cada ramaif/elif
Solo dos casosif/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#

conversor.py
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}")
Salida en pantalla
CONVERSOR DE UNIDADES
Unidades: km, m, cm
Valor: 1500
Unidad de origen: m
Metros:        1,500.000
Kilómetros:        1.500

Fí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 ==.