Python match e case
Quando o programa precisa comparar um mesmo valor com uma lista de opções ("o cliente digitou 1, 2 ou 3?", "a resposta foi sim ou não?", "o comando foi listar, adicionar ou remover?"), uma escada elif resolve, mas repete opcao == em todo degrau. O Python tem um comando feito para isso: o match (em inglês, "combinar", "casar") com os seus case ("caso"). E ele vai além de comparar valores: consegue reconhecer o formato de um comando e separar as partes dele.
- A escrever um
matchcom várioscase, e ocase _para "todo o resto". - A juntar várias opções num caso só com
|("ou"). - A capturar o valor numa variável, e a armadilha de um nome sem aspas.
- Padrões de sequência (com
split(), para entender comandos comoadicionar pão) e de dicionário. - A acrescentar uma condição a um caso com
if(o "guarda"). - Quando usar
matche quando usarif/elif. - Os erros reais do Python 3.14:
name capture … makes remaining patterns unreachable,wildcard makes remaining patterns unreachable,orno lugar de|,casefora domatch, e o caso que nunca casa por causa do tipo.
O match chegou ao Python na versão 3.10, lançada em outubro de 2021. O Python 3.14 deste guia (o do Ubuntu 26.04 e o do editor) tem, e o 3.13 do Debian 13 também. Num Python 3.9 ou mais antigo, um programa com match nem começa a rodar: dá SyntaxError logo na linha do match. Se for escrever um programa que precisa rodar em computadores antigos, confira a versão com python3 --version (aula Instalar o Python) ou use if/elif.
Todos os programas desta aula rodaram no Python 3.14 do computador fictício da Ana (usuária ana, computador notebook), na pasta pessoal dela, com python3 arquivo.py.
A ideia: o atendente da padaria
No balcão da padaria, a Ana recebe o pedido e compara com o cardápio: "é o número 1? Pão francês. É o 2? Pão de queijo. É o 3? Café. Qualquer outra coisa? 'Não temos essa opção'". Ela olha uma coisa (o número pedido) e procura o primeiro caso que combina.
O match é esse atendente: você diz qual valor olhar (match opcao:) e lista os casos (case "1":, case "2":…). O Python testa os casos de cima para baixo e roda o bloco do primeiro que combinar.
1. O primeiro match: o cardápio
print("1 - Pão francês 2 - Pão de queijo 3 - Café")
opcao = input("Escolha: ")
match opcao:
case "1":
print("Pão francês: R$ 0.80")
case "2":
print("Pão de queijo: R$ 4.50")
case "3":
print("Café: R$ 3.00")
case _:
print("Opção inválida.")
print("Obrigado!")
$ python3 menu.py 1 - Pão francês 2 - Pão de queijo 3 - Café Escolha: 2 Pão de queijo: R$ 4.50 « combinou com o case "2" Obrigado! $ python3 menu.py 1 - Pão francês 2 - Pão de queijo 3 - Café Escolha: 9 Opção inválida. « nenhum caso combinou: caiu no case _ Obrigado!
- match opcao:
- "Compare
opcaocom os casos abaixo". O valor depois domatchse chama sujeito. A linha termina com dois-pontos. - case "1":
- Um caso, recuado 4 espaços. O
"1"é o padrão: aqui, um valor fixo. O caso combina quandoopcaoé igual a"1". Entre aspas porque oinput()devolve texto. - o bloco do caso
- Recuado mais 4 espaços (8 no total). Roda só se o caso combinar.
- case _:
- O sublinhado
_é o coringa: combina com qualquer coisa. É o "senão" domatch, e por isso vem sempre por último. - print("Obrigado!")
- De volta à margem: fora do
match, roda sempre.
break)
Como na escada elif, o Python para no primeiro caso que combina; os de baixo nem são testados. Se você conhece o switch de C, Java ou JavaScript, repare: no Python não existe break no fim de cada caso, e um caso nunca "escorrega" para o seguinte.
Para comparar, a mesma coisa com if/elif (que no lab deu exatamente a mesma saída, com a escolha 2):
print("1 - Pão francês 2 - Pão de queijo 3 - Café")
opcao = input("Escolha: ")
if opcao == "1":
print("Pão francês: R$ 0.80")
elif opcao == "2":
print("Pão de queijo: R$ 4.50")
elif opcao == "3":
print("Café: R$ 3.00")
else:
print("Opção inválida.")
print("Obrigado!")
Para comparar valores simples, os dois servem. O match deixa claro, logo na primeira linha, que todos os casos olham para o mesmo valor. A força dele aparece nas seções 4 e 5.
Missão: o cardápio mostra o café, mas o match não tem o caso dele. Acrescente um case "3": que mostre Café: R$ 3.00, antes do case _. A entrada preparada é 3.
print("1 - Pão francês 2 - Pão de queijo 3 - Café")
opcao = input("Escolha: ")
match opcao:
case "1":
print("Pão francês: R$ 0.80")
case "2":
print("Pão de queijo: R$ 4.50")
case _:
print("Opção inválida.")
print("1 - Pão francês 2 - Pão de queijo 3 - Café")
opcao = input("Escolha: ")
match opcao:
case "1":
print("Pão francês: R$ 0.80")
case "2":
print("Pão de queijo: R$ 4.50")
case "3":
print("Café: R$ 3.00")
case _:
print("Opção inválida.")
2. Várias opções num caso: |
Quem responde "sim" pode escrever s, sim, S ou Sim. Em vez de um caso para cada, separe as opções com | (a barra vertical, que aqui quer dizer "ou"):
resposta = input("Confirma o pedido? ")
match resposta:
case "s" | "sim" | "S" | "Sim":
print("Pedido confirmado!")
case "n" | "não" | "nao" | "N":
print("Pedido cancelado.")
case _:
print("Não entendi. Responda sim ou não.")
$ python3 confirma.py Confirma o pedido? Sim Pedido confirmado! $ python3 confirma.py Confirma o pedido? nao Pedido cancelado. $ python3 confirma.py Confirma o pedido? talvez Não entendi. Responda sim ou não.
O caso combina se o valor for igual a qualquer uma das opções. A barra fica no teclado brasileiro (ABNT2) na tecla à esquerda do Z, com Shift.
Sem case _: pode não rodar nada
Como o else da escada elif, o case _ é opcional. Sem ele, se nenhum caso combinar, o match não faz nada:
dia = input("Dia da semana: ")
match dia:
case "sábado" | "domingo":
print("Fim de semana: a padaria abre às 7h.")
case "segunda" | "terça" | "quarta" | "quinta" | "sexta":
print("Dia útil: a padaria abre às 6h.")
$ python3 dia.py Dia da semana: domingo Fim de semana: a padaria abre às 7h. $ python3 dia.py Dia da semana: feriado « nenhum caso combinou: nenhuma mensagem
Missão: este programa só aceita sim, escrito assim. Use | para o primeiro caso aceitar também s, S e Sim. A entrada preparada é S.
resposta = input("Confirma o pedido? ")
match resposta:
case "sim":
print("Pedido confirmado!")
case _:
print("Não entendi.")
resposta = input("Confirma o pedido? ")
match resposta:
case "s" | "sim" | "S" | "Sim":
print("Pedido confirmado!")
case _:
print("Não entendi.")
3. Capturar o valor numa variável
No lugar de um valor fixo, um caso pode ter um nome sem aspas. Esse caso combina com qualquer coisa (como o _), e ainda guarda o valor numa variável com esse nome, para você usar no bloco:
cor = input("Cor do semáforo: ")
match cor:
case "verde":
print("Pode seguir.")
case "vermelho":
print("Pare!")
case outra:
print(f"Não conheço a cor {outra}.")
$ python3 captura.py Cor do semáforo: azul Não conheço a cor azul. « o case outra guardou "azul" em outra
Aqui não faria diferença usar cor no bloco, porque é o mesmo valor. A captura fica útil de verdade quando ela pega só um pedaço do valor, como você vai ver na próxima seção.
No case, um nome simples nunca é comparado com uma variável que já existe: ele sempre captura. Escrever case sim: (sem aspas) não compara com o texto "sim"; combina com tudo e guarda o valor numa variável chamada sim. Valores fixos vão sempre entre aspas (textos) ou como números (case 0:). O Python 3.14 percebe o erro quando há casos depois desse e recusa o programa; veja em Quando dá errado.
4. Padrões de sequência: entender comandos
A Ana quer um programinha de lista de compras que entenda comandos como listar, adicionar manteiga e remover leite. O primeiro passo é separar as palavras com o método split() ("dividir"), da aula Métodos de Texto, que devolve uma lista de palavras (as listas têm aula própria no Nível 2: Listas):
>>> "adicionar manteiga".split() ['adicionar', 'manteiga'] >>> "listar".split() ['listar'] >>> "".split() [] >>> "adicionar ovos queijo presunto".split() ['adicionar', 'ovos', 'queijo', 'presunto']
Agora o match pode olhar o formato da lista: quantas palavras ela tem e qual é a primeira.
comando = input("Comando: ")
match comando.split():
case ["listar"]:
print("Lista: pão, leite, café")
case ["adicionar", item]:
print(f"{item} foi para a lista.")
case ["adicionar", *itens]:
print(len(itens), "itens foram para a lista:", itens)
case ["remover", item]:
print(f"{item} saiu da lista.")
case []:
print("Você não digitou nada.")
case _:
print("Comando desconhecido.")
$ python3 comandos.py Comando: listar Lista: pão, leite, café $ python3 comandos.py Comando: adicionar manteiga manteiga foi para a lista. $ python3 comandos.py Comando: adicionar ovos queijo presunto 3 itens foram para a lista: ['ovos', 'queijo', 'presunto'] $ python3 comandos.py Comando: remover leite leite saiu da lista. $ python3 comandos.py Comando: « a Ana só apertou Enter Você não digitou nada. $ python3 comandos.py Comando: comprar pão Comando desconhecido.
- match comando.split():
- O sujeito é a lista de palavras, e não o texto.
- case ["listar"]:
- Combina com uma lista de exatamente uma palavra, que tem de ser
"listar". - case ["adicionar", item]:
- Lista de exatamente duas palavras: a primeira tem de ser
"adicionar"; a segunda pode ser qualquer uma e é capturada na variávelitem. - case ["adicionar", *itens]:
- O
*quer dizer "o resto, quantas forem". Combina com"adicionar"seguido de qualquer número de palavras, que vão todas paraitens, uma lista. Com uma palavra só, o caso de cima já tinha combinado antes: a ordem dos casos importa, como noelif. - case []:
- A lista vazia: a pessoa não digitou nenhuma palavra.
- case _:
- Todo o resto, como
comprar pão(a primeira palavra não bate com nenhum caso).
Com if/elif, cada caso precisaria conferir o tamanho da lista, a primeira palavra e depois separar a segunda. O match faz as três coisas num padrão só.
Experimente: rode e digite comandos no terminal da caixa: listar, adicionar café, adicionar ovos e farinha, remover (sem item), LISTAR. Depois acrescente um caso para o comando limpar, que mostre "A lista está vazia.".
comando = input("Comando: ")
match comando.split():
case ["listar"]:
print("Lista: pão, leite, café")
case ["adicionar", item]:
print(f"{item} foi para a lista.")
case ["adicionar", *itens]:
print(len(itens), "itens foram para a lista:", itens)
case ["remover", item]:
print(f"{item} saiu da lista.")
case []:
print("Você não digitou nada.")
case _:
print("Comando desconhecido.")
5. Padrões de dicionário
Um dicionário guarda valores com etiquetas (as chaves): {"tipo": "pizza", "sabor": "calabresa"}. Ele tem aula própria no Nível 2 (Dicionários); aqui basta saber que é assim que muitos programas recebem pedidos, cadastros e dados da internet. O match reconhece um dicionário pelas chaves e valores que ele tem:
pedido = {"tipo": "pizza", "sabor": "calabresa", "tamanho": "G"}
match pedido:
case {"tipo": "pizza", "sabor": sabor}:
print(f"Uma pizza de {sabor} saindo!")
case {"tipo": "suco", "fruta": fruta}:
print(f"Um suco de {fruta}.")
case _:
print("Pedido estranho.")
pedido = {"tipo": "suco", "fruta": "caju"}
match pedido:
case {"tipo": "pizza", "sabor": sabor}:
print(f"Uma pizza de {sabor} saindo!")
case {"tipo": "suco", "fruta": fruta}:
print(f"Um suco de {fruta}.")
case _:
print("Pedido estranho.")
$ python3 pedido.py Uma pizza de calabresa saindo! Um suco de caju.
- {"tipo": "pizza", …}
- O dicionário precisa ter a chave
"tipo"com o valor"pizza". - "sabor": sabor
- …e também a chave
"sabor", com qualquer valor, que é capturado na variávelsabor. - a chave "tamanho"
- Não aparece no padrão, e mesmo assim o primeiro pedido combinou: no padrão de dicionário, chaves a mais não atrapalham. Só as chaves escritas no padrão são conferidas. (Na sequência é diferente: o tamanho da lista tem de bater.)
6. Uma condição a mais: o guarda if
Depois do padrão, você pode acrescentar if condição. O caso só combina se o padrão combinar e a condição for verdadeira. Esse if se chama guarda (em inglês, guard):
temperatura = int(input("Temperatura: "))
match temperatura:
case t if t < 0:
print("Abaixo de zero: está congelando!")
case 0:
print("Exatamente zero grau.")
case t if t >= 30:
print("Calor! Beba água.")
case _:
print("Temperatura agradável.")
$ python3 guarda.py Temperatura: -5 Abaixo de zero: está congelando! $ python3 guarda.py Temperatura: 0 Exatamente zero grau. $ python3 guarda.py Temperatura: 33 Calor! Beba água. $ python3 guarda.py Temperatura: 22 Temperatura agradável.
case t if t < 0: se lê: "captura o valor em t, se t for menor que zero". O case 0: é um valor fixo (um número, sem aspas, porque a temperatura foi convertida com int()). Um exemplo em que o guarda combina melhor com o match: o caixa eletrônico por comandos.
saldo = 200.0
comando = input("Comando: ")
match comando.split():
case ["saldo"]:
print(f"Saldo: R$ {saldo:.2f}")
case ["sacar", valor] if float(valor) <= saldo:
saldo = saldo - float(valor)
print(f"Saque feito. Saldo: R$ {saldo:.2f}")
case ["sacar", valor]:
print(f"Saldo insuficiente para sacar R$ {float(valor):.2f}.")
case _:
print("Comando desconhecido.")
$ python3 saque.py Comando: saldo Saldo: R$ 200.00 $ python3 saque.py Comando: sacar 50 Saque feito. Saldo: R$ 150.00 $ python3 saque.py Comando: sacar 500 Saldo insuficiente para sacar R$ 500.00. « o guarda deu False: caiu no caso de baixo
Os dois casos ["sacar", valor] têm o mesmo padrão. O primeiro só vale quando o guarda é verdadeiro; quando não é, o Python continua procurando e encontra o segundo.
Formas diferentes: match × if/elif
| Situação | Use | Por quê |
|---|---|---|
| Um valor comparado com várias opções fixas (menu, sim/não, dias) | match ou if/elif | Os dois servem; o match evita repetir opcao == e o | junta opções |
| Faixas de valores (nota ≥ 9, ≥ 7…) | if/elif | Com match, cada faixa precisaria de um guarda; a escada fica mais simples |
Comandos com partes (adicionar pão), listas e dicionários com formatos diferentes | match | Confere o formato e separa as partes numa linha só |
| Condições sobre coisas diferentes (idade e cidade e saldo) | if/elif | O match olha um sujeito só |
| Programa que precisa rodar em Python 3.9 ou mais antigo | if/elif | O match só existe a partir do 3.10 |
match e case ainda podem ser nomes
Para não quebrar programas antigos, match e case são palavras-chave "leves" (soft keywords): só são especiais no começo de um match. Em qualquer outro lugar, ainda podem ser nomes de variáveis. No lab, match = "Ana e Bia", case = 3 e print(match, case) rodaram sem erro e mostraram Ana e Bia 3. Funciona, mas evite: confunde quem lê.
Quando dá errado
case
resposta = "não"
match resposta:
case sim:
print("Confirmado!")
case _:
print("Cancelado.")
$ python3 sem_aspas.py
File "/home/ana/sem_aspas.py", line 3
case sim:
^^^
SyntaxError: name capture 'sim' makes remaining patterns unreachable
Linha por linha:
line 3e^^^embaixo desim: o problema é esse padrão.name capture 'sim': "captura de nome'sim'". Sem aspas,simnão é o texto "sim": é um nome que captura qualquer valor (seção 3).makes remaining patterns unreachable: "torna os padrões seguintes inalcançáveis". Como esse caso combina com tudo, ocase _de baixo nunca seria alcançado, e o Python recusa o programa.
Como consertar: case "sim":, com aspas.
case
O mesmo acontece com uma variável que você criou antes, mesmo com nome em maiúsculas:
VERDE = "verde"
cor = "vermelho"
match cor:
case VERDE:
print("Pode seguir.")
case "vermelho":
print("Pare!")
$ python3 captura_errada.py
File "/home/ana/captura_errada.py", line 4
case VERDE:
^^^^^
SyntaxError: name capture 'VERDE' makes remaining patterns unreachable
E se não houver caso depois, o Python não tem como avisar, e o resultado é pior: o programa roda errado.
VERDE = "verde"
cor = "vermelho"
match cor:
case VERDE:
print("Pode seguir.")
print("cor agora vale:", cor, "/ VERDE agora vale:", VERDE)
$ python3 captura_errada2.py Pode seguir. « com o sinal vermelho! cor agora vale: vermelho / VERDE agora vale: vermelho « e a "constante" foi trocada
O case VERDE: capturou "vermelho" na variável VERDE, por cima do valor antigo. Como consertar: escreva o valor (case "verde":). Valores guardados com nome só são comparados quando têm um ponto no meio, como case Cor.VERDE:, um recurso da aula Enum.
opcao = "1"
match opcao:
case _:
print("Opção inválida.")
case "1":
print("Pão francês")
$ python3 coringa_antes.py
File "/home/ana/coringa_antes.py", line 3
case _:
^
SyntaxError: wildcard makes remaining patterns unreachable
"O coringa torna os padrões seguintes inalcançáveis". Como o case _ combina com tudo e os casos são testados em ordem, o case "1" nunca seria alcançado. Como consertar: o case _ é sempre o último.
or no lugar de |
resposta = "s"
match resposta:
case "s" or "sim":
print("Confirmado!")
$ python3 com_or.py
File "/home/ana/com_or.py", line 3
case "s" or "sim":
^^
SyntaxError: invalid syntax
Dentro de um padrão, "ou" se escreve com a barra |, e não com or. Como consertar: case "s" | "sim":.
opcao = int(input("Escolha: "))
match opcao:
case "1":
print("Pão francês")
case _:
print("Opção inválida.")
$ python3 numero_texto.py Escolha: 1 Opção inválida. « o número 1 não é igual ao texto "1"
Sem erro nenhum. A opção foi convertida para número com int(), e o caso compara com o texto "1". Para o Python, 1 e "1" são diferentes. Como consertar: escolha um tipo e use nos dois lugares: sem int() e case "1":, ou com int() e case 1:.
O match segue as mesmas regras de dois-pontos e recuo do if. Três programas com erro:
opcao = "1"
match opcao
case "1":
print("Pão francês")
opcao = "1"
match opcao:
case "1":
print("Pão francês")
opcao = "1"
case "1":
print("Pão francês")
$ python3 sem_dois_pontos.py
File "/home/ana/sem_dois_pontos.py", line 2
match opcao
^
SyntaxError: expected ':'
$ python3 case_sem_recuo.py
File "/home/ana/case_sem_recuo.py", line 3
case "1":
^^^^
IndentationError: expected an indented block after 'match' statement on line 2
$ python3 case_sozinho.py
File "/home/ana/case_sozinho.py", line 2
case "1":
^^^
SyntaxError: invalid syntax
sem_dois_pontos.py: faltaram os dois-pontos depois dematch opcao.case_sem_recuo.py: ocaseficou na margem, na mesma coluna domatch. Os casos são o bloco domatche têm de estar recuados.case_sozinho.py: umcasesemmatchantes. Fora de ummatch,casenão quer dizer nada, e o Python acha a linha sem sentido.
Referência rápida
| Padrão | Combina com |
|---|---|
case "sim": / case 0: | Exatamente esse valor |
case "s" | "sim": | Qualquer uma das opções |
case _: | Qualquer coisa (o "senão"; sempre por último) |
case nome: | Qualquer coisa, e guarda o valor em nome |
case ["listar"]: | Lista com exatamente esse item |
case ["adicionar", item]: | Lista de 2 itens, o primeiro "adicionar"; o segundo vai para item |
case ["adicionar", *itens]: | "adicionar" seguido de quantos itens forem, guardados em itens |
case []: | Lista vazia |
case {"tipo": "pizza", "sabor": s}: | Dicionário com essas chaves (outras chaves não atrapalham) |
case padrão if condição: | O padrão, e só se a condição (o guarda) for verdadeira |
| Sintoma | Causa provável |
|---|---|
SyntaxError: name capture 'x' makes remaining patterns unreachable | Um nome sem aspas no case (texto sem aspas ou variável): ele captura tudo |
SyntaxError: wildcard makes remaining patterns unreachable | case _ antes de outros casos |
SyntaxError: invalid syntax num case com or | Use | para juntar opções |
SyntaxError: invalid syntax num case solto | case sem match antes |
IndentationError: expected an indented block after 'match' statement | Os case não estão recuados |
Cai sempre no case _ | Tipos diferentes: número no sujeito e texto no case (ou o contrário); ou maiúsculas e minúsculas |
| Um caso "sem aspas" combina com tudo, sem erro | Captura de nome no último caso: o valor foi guardado na variável |
SyntaxError logo na linha do match, num computador antigo | Python 3.9 ou anterior: o match só existe a partir do 3.10 |
Exercícios
1. Complete o match
Complete as duas palavras-chave:
"1":
print("Pão francês")
2. O coringa
Qual caractere, no case, combina com qualquer valor?
3. A partir de qual versão?
O match existe a partir de qual versão do Python? (Escreva como 3.x.)
4. O que este programa mostra?
fruta = "caju"
match fruta:
case "maçã" | "pera":
print("Fruta de clima frio")
case "caju" | "manga":
print("Fruta tropical")
case _:
print("Não sei")
5. Com match "remover pão leite".split():, qual destes casos combina?
6. Por que case sim: (sem aspas) é um erro de lógica?
Missão final: depósito no caixa
Missão: o caixa por comandos entende saldo e sacar VALOR. Acrescente um caso para depositar VALOR (antes do case _), que some o valor ao saldo e mostre Depósito feito. Saldo: R$ …, com duas casas decimais. A entrada preparada é depositar 50; com o saldo de 200, a saída tem de ser Depósito feito. Saldo: R$ 250.00.
saldo = 200.0
comando = input("Comando: ")
match comando.split():
case ["saldo"]:
print(f"Saldo: R$ {saldo:.2f}")
case ["sacar", valor] if float(valor) <= saldo:
saldo = saldo - float(valor)
print(f"Saque feito. Saldo: R$ {saldo:.2f}")
case ["sacar", valor]:
print("Saldo insuficiente.")
case _:
print("Comando desconhecido.")
saldo = 200.0
comando = input("Comando: ")
match comando.split():
case ["saldo"]:
print(f"Saldo: R$ {saldo:.2f}")
case ["sacar", valor] if float(valor) <= saldo:
saldo = saldo - float(valor)
print(f"Saque feito. Saldo: R$ {saldo:.2f}")
case ["sacar", valor]:
print("Saldo insuficiente.")
case ["depositar", valor]:
saldo = saldo + float(valor)
print(f"Depósito feito. Saldo: R$ {saldo:.2f}")
case _:
print("Comando desconhecido.")
Para ir além: acrescente um guarda para recusar depósitos de valor zero ou negativo (case ["depositar", valor] if float(valor) > 0:) e um caso logo abaixo dele com a mensagem de valor inválido.
Resumo
match valor:compara um valor (o sujeito) com várioscase, de cima para baixo, e roda só o bloco do primeiro que combinar. Não existebreak, nem "escorregar" para o caso seguinte.- Só existe a partir do Python 3.10; num Python mais antigo, é
SyntaxError. case "x":compara com um valor fixo;case "a" | "b":aceita várias opções;case _:é o "senão", sempre por último.- Um nome sem aspas no
casecaptura o valor (e combina com tudo): textos fixos vão sempre entre aspas. - Padrões de sequência (
["adicionar", item],*itens,[]) conferem o formato de uma lista e separam as partes; padrões de dicionário conferem chaves e valores (chaves a mais não atrapalham). case padrão if condição:acrescenta um guarda: o caso só vale se a condição também for verdadeira.- Para faixas de valores ou condições sobre coisas diferentes, o
if/elifcontinua sendo a escolha.