6. Muitos caminhos¶
Nesta aula
Ideia central: quando os casos são três ou mais, if seguido de if
não é a mesma coisa que if seguido de elif. A diferença não dá erro
nenhum: ela só troca o resultado.
Ao fim você vai conseguir: escrever uma escada de elif; pôr as faixas
na ordem certa; combinar condições com and, or e not; e reconhecer as
três armadilhas deste capítulo, que são as mais caras do semestre.
Três casos, não dois¶
O capítulo passado resolveu escolhas de dois caminhos. A maior parte dos problemas reais tem mais: a conta do celular tem três faixas de preço, a nota tem aprovado, recuperação e reprovado, a idade tem três categorias.
Para isso existe o elif — contração de else if, "senão, se":
# Uma escolha entre tres precos: exatamente um dos blocos roda.
minutos = 137
if minutos < 200:
preco = 0.20
elif minutos < 400:
preco = 0.18
else:
preco = 0.15
print(f"{minutos} minutos a R$ {preco:.2f} = R$ {minutos * preco:.2f}")
A estrutura completa é esta, e a ordem das palavras é obrigatória:
ifvem uma vez, no começo;elifpode vir quantas vezes você precisar, cada um com a sua condição;elseé opcional e vem por último, sem condição.
E a propriedade que vale ouro: o Python testa as condições de cima para
baixo e para no primeiro True. Os testes seguintes nem chegam a ser
avaliados. Exatamente um bloco roda.
💡 Pense assim: a triagem do posto de saúde
Na entrada, uma pergunta de cada vez: é emergência? Não. É urgência? Não. É consulta marcada? Sim — e a pessoa vai para a fila da consulta. A triagem para ali; ninguém continua perguntando depois que já encaminhou o paciente.
Uma escada de elif faz isso. Uma sequência de if independentes faz outra
coisa: pergunta todas, sempre, e vale a última resposta.
Armadilha 1 · if seguido de if¶
Aqui está o assunto central desta unidade. O programa abaixo tem o mesmo
objetivo do anterior e uma diferença de duas letras: elif virou if.
# O MESMO problema, com if no lugar de elif. Repare no preco que sai.
minutos = 137
if minutos < 200:
preco = 0.20
if minutos < 400:
preco = 0.18
if minutos >= 400:
preco = 0.15
print(f"{minutos} minutos a R$ {preco:.2f} = R$ {minutos * preco:.2f}")
O preço certo, para 137 minutos, é R$ 0,20 — a fatura sai a R$ 27,40. Este programa cobrou R$ 0,18 e fechou a conta em R$ 24,66.
Rastreie, como na Lista 02:
| Linha | Condição | Vale? | preco |
|---|---|---|---|
if minutos < 200: |
137 < 200 | sim | 0.20 |
if minutos < 400: |
137 < 400 | sim | 0.18 |
if minutos >= 400: |
137 >= 400 | não | 0.18 |
São três if independentes. Todos os três são avaliados, um depois do
outro, e o segundo sobrescreveu tranquilamente o valor que o primeiro tinha
guardado. Não há erro de sintaxe, não há aviso, não há nada: o programa roda
inteiro e imprime um número com a maior cara de certo.
O erro que não se denuncia — agora com if
Repare no tamanho do estrago: R$ 24,66 em vez de R$ 27,40. É um número plausível, na ordem de grandeza certa, com as duas casas decimais no lugar. Numa fatura entre milhares, ninguém percebe.
Este é o mesmo modo de falha da precedência na Unidade 1 e da conversão esquecida na Lista 03, e é a assinatura do código gerado por assistente de IA: sintaxe impecável, execução limpa, resultado errado. O único antídoto é você saber qual resposta esperar antes de rodar.
A regra prática: se os casos são alternativos — se um exclui o outro —
use elif. if repetido só se justifica quando as perguntas são mesmo
independentes e mais de uma pode valer ao mesmo tempo.
Armadilha 2 · a ordem dos testes¶
Corrigido o elif, sobra o erro irmão, que é ainda mais discreto. Os três
testes abaixo estão corretos, um por um. A ordem deles é que não está.
# Os testes estao certos, um por um. A ordem deles e que esta errada.
minutos = 520
if minutos >= 200:
preco = 0.18
elif minutos >= 400:
preco = 0.15
else:
preco = 0.20
print(f"{minutos} minutos a R$ {preco:.2f} = R$ {minutos * preco:.2f}")
520 minutos deveriam sair a R$ 0,15. Saíram a R$ 0,18, porque 520 >= 200 é
verdadeiro — e, sendo o primeiro teste da escada, ele pegou o cliente e a
escada parou ali. O elif minutos >= 400 está no programa e nunca vai rodar
para valor nenhum: todo mundo que passa de 400 também passa de 200.
A correção não mexe em nenhuma condição, só na ordem:
# A mesma faixa, testada da ponta mais exigente para a menos exigente.
minutos = 520
if minutos >= 400:
preco = 0.15
elif minutos >= 200:
preco = 0.18
else:
preco = 0.20
print(f"{minutos} minutos a R$ {preco:.2f} = R$ {minutos * preco:.2f}")
💡 Pense assim: a peneira mais fina primeiro
Peneiras empilhadas separam grãos por tamanho, e a ordem é obrigatória: a de malha mais fina vai em cima. Se a mais grossa ficar em cima, tudo passa por ela e as outras nunca recebem nada.
Numa escada de elif, a "peneira mais fina" é a condição mais difícil de
satisfazer — a que menos gente atende.
Daí a regra das faixas, que resolve o problema de uma vez:
- com
>=, comece pela maior faixa e vá descendo; - com
<=ou<, comece pela menor e vá subindo; - nunca misture os dois sentidos na mesma escada.
E um teste que você pode fazer no papel, sempre: pegue um valor de cada faixa —
inclusive os valores de fronteira, 200 e 400 — e siga a escada com o dedo.
Se algum valor cair na faixa errada, ou se algum elif nunca for alcançado, o
problema é a ordem.
Operadores lógicos: juntando condições¶
Às vezes uma condição só não basta. Para entrar no brinquedo do parque é preciso ter pelo menos 12 anos e 1,50 m. Para isso existem três operadores:
idade = 14
altura = 1.62
print(idade >= 12 and altura >= 1.50)
print(idade >= 12 or altura >= 1.50)
print(not (idade >= 12))
# and so e verdadeiro quando os DOIS sao; or, quando pelo menos um e.
print(True and False, True or False, not True)
| Operador | Verdadeiro quando |
|---|---|
and |
as duas condições são verdadeiras |
or |
pelo menos uma é verdadeira |
not |
inverte: transforma True em False e vice-versa |
Em português, and é o "e" exigente e or é o "ou" generoso. E cuidado com o
português falado, que engana: "clientes do plano A ou do plano B pagam menos"
é um or; "tem de ter idade e altura" é um and.
💡 Pense assim: os documentos na portaria
and é a portaria que pede RG e crachá: faltou um, não entra. or é a
que aceita RG ou crachá: qualquer um dos dois serve, e os dois juntos
também servem.
not é a lista de barrados: quem está nela não entra, quem não está, entra.
Quando misturar os três, use parênteses. Vale aqui a mesma recomendação do
capítulo 4: and tem precedência sobre or, você não precisa decorar isso, e
os parênteses deixam a sua intenção explícita para quem lê.
Armadilha 3 · or com o valor solto¶
Esta é a que mais aparece em prova, e ela nasce justamente de escrever o programa como se fala. "Se o dia for sábado ou domingo" vira, quase sozinho, isto:
# Este programa roda, nao reclama - e responde errado.
dia = "sabado"
if dia == "sabado" or "domingo":
print("Fim de semana")
else:
print("Dia util")
dia = "quarta"
if dia == "sabado" or "domingo":
print("Fim de semana")
else:
print("Dia util")
# Por que? Porque "domingo" sozinho, para o Python, ja vale verdadeiro.
print(bool("domingo"), bool(""))
Os dois casos imprimiram Fim de semana — inclusive o segundo, em que dia
vale "quarta". A condição é sempre verdadeira, para qualquer valor.
O motivo está na última linha da saída. O Python lê dia == "sabado" or
"domingo" como duas partes separadas por or:
dia == "sabado"— uma comparação, que valeFalse;"domingo"— um texto solto, que não compara nada com ninguém.
E, para o Python, qualquer texto não vazio vale como verdadeiro. or então
encontra uma das partes verdadeira e devolve True, sempre. O else do
programa é código morto.
A correção é repetir o nome da variável em cada comparação:
dia = "quarta"
if dia == "sabado" or dia == "domingo":
print("Fim de semana")
else:
print("Dia util")
Toda comparação precisa dos dois lados
or não distribui o dia == para a direita, por mais que a frase em
português distribua. Cada lado de um and ou de um or tem de ser uma
condição completa, com os dois lados e o operador no meio.
Guarde o sintoma: um programa em que um dos caminhos nunca acontece, aconteça o que acontecer, quase sempre é isto.
if dentro de if¶
Um if pode morar dentro do bloco de outro, com mais quatro espaços de recuo.
Serve para as perguntas que só fazem sentido depois de uma primeira resposta:
# Um if dentro do outro: a segunda pergunta so faz sentido depois da primeira.
minutos = 520
plano = "controle"
if minutos >= 400:
if plano == "controle":
preco = 0.12
else:
preco = 0.15
else:
preco = 0.20
print(f"Plano {plano}, {minutos} minutos: R$ {preco:.2f} por minuto")
A pergunta sobre o plano só é feita para quem passou de 400 minutos; abaixo disso, o preço é o mesmo para todo mundo e o plano é irrelevante.
Duas recomendações, nesta ordem de importância:
- Alinhe com cuidado. O
elsede dentro pertence aoifde dentro porque está na margem dele. Movê-lo quatro espaços para a esquerda muda o programa sem dar erro nenhum — mais um da família. - Não passe de dois níveis. Se você chegar ao terceiro, quase sempre dá
para trocar o aninhamento por um
and:if a:comif b:dentro faz o mesmo queif a and b:, e se lê muito melhor.
Validar antes de classificar¶
Uma escada de elif bem escrita costuma começar peneirando o que nem deveria
ter chegado ali:
idade = int(input("Idade do participante: "))
if idade <= 0:
print("Idade invalida.")
elif idade <= 12:
print("Categoria: Infantil")
elif idade <= 17:
print("Categoria: Juvenil")
else:
print("Categoria: Adulto")
O primeiro teste não classifica nada: ele rejeita. Idade negativa não é infantil, é entrada inválida, e separar as duas coisas na primeira linha da escada deixa o resto simples — dali para baixo, você já sabe que o valor é positivo.
Erros comuns deste capítulo¶
| Mensagem ou sintoma | Causa provável |
|---|---|
SyntaxError: invalid syntax na linha do elif |
escreveu else if ou elseif; em Python é elif |
SyntaxError num elif depois do else |
o else tem de ser o último da escada |
| o resultado é sempre o da última faixa | são if independentes; o de baixo sobrescreveu |
um dos elif nunca acontece |
ordem errada: um teste de cima já captura esses valores |
| um dos caminhos acontece sempre | or com valor solto: falta repetir variavel == |
| o valor da fronteira cai na faixa errada | > onde devia ser >= |
NameError numa variável criada dentro de um if |
o bloco não rodou, então ela nunca foi criada |
TypeError ao comparar texto com número |
faltou int() ou float() no input() |
Resumo¶
if/elif/elif/else: testado de cima para baixo, para no primeiro verdadeiro, exatamente um bloco roda.ifseguido deifavalia todos os testes, e o último a atribuir vence. É a troca mais cara de duas letras do semestre.- Em faixas com
>=, comece pela maior. Com<=, pela menor. Confira as fronteiras no papel. andexige as duas;oraceita uma;notinverte. Parênteses quando misturar.dia == "sabado" or "domingo"é sempre verdadeiro. Cada lado doorprecisa ser uma comparação completa.ifaninhado serve para a pergunta que depende da anterior; a partir de dois níveis, prefiraand.- Nenhum dos três erros deste capítulo dá mensagem de erro. Todos entregam um resultado plausível e errado.
Para praticar¶
Lista 06 · Muitos caminhos. O exercício final é um programa que já vem escrito e errado — do jeito exato da Armadilha 3. Ele fecha a Unidade 2, e a Unidade 3 começa com o programa aprendendo a repetir.