Sua dose diária de programação

Conceito, 3 exemplos e 3 exercícios: uma pequena conquista de cada vez.

✦   Lição

Decisões com condicionais

Até aqui os programas rodavam todas as linhas, de cima para baixo. Com o if, o programa passa a decidir: um bloco de código só é executado quando uma condição é verdadeira. Em Python, o bloco é marcado pela indentação (quatro espaços, por convenção) depois dos dois-pontos; não há chaves.

Python Fundamentos Iniciante 3 exemplos + 3 exercícios
42 lições publicadas 10 linguagens novas lições todo dia útil
Python / Fundamentos

Decisões com condicionais

por Briar Westbrook
Iniciante

Entenda o conceito

Até aqui os programas rodavam todas as linhas, de cima para baixo. Com o if, o programa passa a decidir: um bloco de código só é executado quando uma condição é verdadeira. Em Python, o bloco é marcado pela indentação (quatro espaços, por convenção) depois dos dois-pontos; não há chaves.

else cobre o caso contrário e elif (abreviação de "else if") testa novas condições em sequência. O Python avalia as condições de cima para baixo e executa só o primeiro bloco verdadeiro, por isso a ordem das condições importa.

As condições combinam comparações (==, !=, <, >=...) com os operadores lógicos and, or e not, e o Python aceita comparações encadeadas como 1 <= x <= 12. Valores como 0, "", None e listas vazias contam como falsos. Para escolher entre dois valores numa linha existe a expressão condicional (a if condição else b), e para comparar um valor com vários padrões, o match/case, disponível desde o Python 3.10.

↳ Pontos-chave
  • if condição: seguido de um bloco indentado; o bloco só roda quando a condição é True.
  • Em if/elif/else, só o primeiro bloco verdadeiro é executado: ordene as condições da mais específica para a mais geral.
  • and exige as duas condições, or aceita qualquer uma e not inverte; 1 <= x <= 12 é uma comparação encadeada válida.
  • 0, 0.0, "", None e coleções vazias são falsos num if; quase todo o resto é verdadeiro.
  • valor = a if condição else b escolhe um valor numa linha; match/case compara um valor com vários padrões, e case _ pega o resto.

Do conceito à prática

3 exemplos para ver a ideia funcionando.

01Devolução na biblioteca com if, elif e else

emprestimo.py
# emprestimo.py: if, elif e else decidem o que o programa faz.

dias_com_o_livro = 18
PRAZO = 14  # dias permitidos para cada empréstimo

# if: o bloco indentado só roda quando a condição é True.
if dias_com_o_livro > PRAZO:
    print("Atenção: o prazo de devolução já passou.")

# if/else: exatamente um dos dois blocos roda.
atraso = dias_com_o_livro - PRAZO
if atraso > 0:
    print(f"Atraso de {atraso} dias.")
else:
    print("Devolução dentro do prazo.")

# if/elif/else: as condições são testadas de cima para baixo
# e só o primeiro bloco verdadeiro é executado.
if atraso <= 0:
    situacao = "regular"
elif atraso <= 7:
    situacao = "advertência"
elif atraso <= 30:
    situacao = "multa"
else:
    situacao = "suspensão"

print(f"Situação do leitor: {situacao}")
print("Fim da consulta.")  # fora dos blocos: sempre roda

O exemplo mostra as três formas do if. O primeiro só imprime o aviso quando o prazo passou; o segundo, com else, sempre imprime uma de duas mensagens; o terceiro escolhe uma entre quatro situações com elif.

Na cadeia de elif, um atraso de 4 dias também é menor que 30, mas a situação fica advertência porque o Python para no primeiro teste verdadeiro. A última linha, sem indentação, está fora de qualquer bloco e roda sempre.

02Ingredientes da receita com and, or e not

receita.py
# receita.py: and, or, not, comparação encadeada e valores "falsos".

porcoes = 6
tem_ovos = True
tem_leite = False
observacao = ""  # texto vazio

# Comparação encadeada: equivale a 1 <= porcoes and porcoes <= 12.
if 1 <= porcoes <= 12:
    print(f"{porcoes} porções: a receita cabe numa forma só.")

# and exige as duas condições; or aceita qualquer uma.
if tem_ovos and tem_leite:
    print("Dá para fazer o bolo tradicional.")
elif tem_ovos or tem_leite:
    print("Falta um ingrediente: use a versão adaptada.")
else:
    print("Melhor escolher outra receita.")

# not inverte o valor lógico.
if not tem_leite:
    print("Lista de compras: leite.")

# Texto vazio, 0, None e listas vazias contam como False num if.
if observacao:
    print(f"Observação: {observacao}")
else:
    print("Nenhuma observação para esta receita.")

# O operador in também gera um bool e combina bem com if.
ingrediente = "fermento"
if ingrediente in ("farinha", "açúcar", "fermento"):
    print(f"{ingrediente.capitalize()} está na despensa.")

Aqui as condições ficam mais ricas. A comparação encadeada 1 <= porcoes <= 12 lê como na matemática, and e or combinam dois testes e not inverte um valor lógico. Como há ovos mas não há leite, o and é falso e o or é verdadeiro.

O if observacao: aproveita a regra de que texto vazio vale False, um atalho idiomático para perguntar "tem alguma coisa aqui?". Por fim, in testa se um valor está numa sequência e também devolve um bool.

03Comandos de um jogo com expressão condicional e match

comandos.py
# comandos.py: expressão condicional e match/case num jogo de texto.

def descrever_vida(vida):
    # Expressão condicional: valor_se_verdadeiro if condição else valor_se_falso
    estado = "em perigo" if vida < 30 else "bem"
    return f"Vida {vida}: herói {estado}"


def executar(comando, chaves):
    # match compara o valor com cada case, de cima para baixo.
    match comando:
        case "norte" | "sul" | "leste" | "oeste":
            return f"Você caminha para o {comando}."
        case "abrir" if chaves > 0:  # guarda: o case só vale se o if for True
            return "A porta range e se abre."
        case "abrir":
            return "A porta está trancada. Procure uma chave."
        case "sair":
            return "Até a próxima aventura!"
        case _:  # curinga: qualquer outro valor
            return f"Comando desconhecido: {comando}"


def main():
    print(descrever_vida(80))
    print(descrever_vida(12))
    print()
    print(executar("norte", 0))
    print(executar("abrir", 0))
    print(executar("abrir", 1))
    print(executar("dançar", 0))
    print(executar("sair", 0))


if __name__ == "__main__":
    main()

Em descrever_vida(), a expressão condicional escolhe o texto do estado numa linha só, sem um if de quatro linhas. Ela serve quando o objetivo é produzir um valor, não executar blocos diferentes.

Em executar(), o match compara o comando com cada case: | junta várias opções, a guarda if chaves > 0 só deixa o case valer quando há chave, e case _ pega qualquer comando desconhecido. Como o primeiro case "abrir" falha sem chave, o Python segue para o segundo.


Agora é com você

Tente resolver no rascunho antes de abrir a resposta. Os códigos não são executados nesta página.

01Faixas de frete da lojaFácil

Escreva a função mostrar_frete(total), que mostra o frete de uma compra: grátis a partir de R$ 200, R$ 9.90 a partir de R$ 100 e R$ 19.90 abaixo disso. Chame a função para as compras de 250, 120, 45.5 e 200 reais.

↳ Requisitos
  • A escolha da faixa usa uma única cadeia if/elif/else.
  • Uma compra de exatamente R$ 200 tem frete grátis.
  • O valor da compra aparece com duas casas decimais (:.2f).
  • A saída tem exatamente 4 linhas, uma por chamada.
código inicial
# frete.py: faixas de frete da loja com if/elif/else.


def mostrar_frete(total):
    pass  # troque pela cadeia de if/elif/else


mostrar_frete(250)
mostrar_frete(120)
mostrar_frete(45.5)
mostrar_frete(200)
saída esperada
Compra de R$ 250.00: frete grátis
Compra de R$ 120.00: frete de R$ 9.90
Compra de R$ 45.50: frete de R$ 19.90
Compra de R$ 200.00: frete grátis
Ver dica

Comece pela faixa mais alta: se o primeiro teste for total >= 100, a compra de 250 reais nunca chega ao frete grátis.

Ver resposta
# frete.py: faixas de frete da loja com if/elif/else.


def mostrar_frete(total):
    # As faixas vão da maior para a menor: a primeira verdadeira vence.
    if total >= 200:
        print(f"Compra de R$ {total:.2f}: frete grátis")
    elif total >= 100:
        print(f"Compra de R$ {total:.2f}: frete de R$ 9.90")
    else:
        print(f"Compra de R$ {total:.2f}: frete de R$ 19.90")


mostrar_frete(250)
mostrar_frete(120)
mostrar_frete(45.5)
mostrar_frete(200)

Passo a passo

  1. def mostrar_frete(total): define a função; o valor da compra chega pelo parâmetro total a cada chamada.
  2. if total >= 200: testa primeiro a faixa mais alta. O >= (e não >) garante que exatamente 200 reais também tenha frete grátis.
  3. elif total >= 100: só é avaliado quando o teste anterior falhou, então aqui já se sabe que a compra está abaixo de 200.
  4. else: não tem condição: cobre todas as compras que não entraram nas faixas anteriores, ou seja, abaixo de 100.
  5. Nas f-strings, {total:.2f} mostra o valor com duas casas, por isso 45.5 aparece como 45.50 e 250 como 250.00.
  6. As quatro chamadas no fim, sem indentação, ficam fora da função e são o que de fato executa o programa.

Por que funciona

Cada chamada passa por uma única cadeia if/elif/else, e o Python executa só o primeiro bloco cuja condição é verdadeira. Por isso as faixas podem ser escritas só com o limite de baixo: quem chega ao elif já não tem 200 reais ou mais.

O else garante que toda compra recebe exatamente uma mensagem, sem lacunas entre as faixas.

Erros comuns

  • Testar total >= 100 antes de total >= 200: a compra de 250 reais cai na primeira faixa verdadeira e recebe frete de 9.90. Ordene da faixa mais alta para a mais baixa.
  • if total > 200:: a compra de exatamente 200 reais paga frete, contrariando a regra. Use >=.
  • Usar três if independentes em vez de elif: a compra de 250 reais imprime duas linhas, porque também é >= 100. Encadeie com elif.
  • Esquecer os dois-pontos em else: dá SyntaxError: expected ':'. Todo if, elif e else termina com :.

Outra forma de resolver

A função pode calcular só o valor do frete e deixar a impressão para o fim: frete = 0 if total >= 200 else 9.90 if total >= 100 else 19.90. Expressões condicionais aninhadas ficam difíceis de ler com mais de duas opções, então a cadeia de elif continua sendo a forma mais clara aqui.

Saída esperada

Compra de R$ 250.00: frete grátis
Compra de R$ 120.00: frete de R$ 9.90
Compra de R$ 45.50: frete de R$ 19.90
Compra de R$ 200.00: frete grátis

02Quem pode pegar livros emprestadosMédio

Escreva a função avaliar(nome, ativo, multa, livros) que libera um empréstimo só para leitores com cadastro ativo, sem multa e com menos de 3 livros em mãos. Quando recusar, a função mostra o primeiro motivo, na ordem: cadastro, multa, limite.

↳ Requisitos
  • A liberação usa uma única condição com and reunindo as três regras.
  • O cadastro inativo é testado com not ativo.
  • O limite de livros fica numa constante LIMITE_LIVROS = 3 usada na condição e na mensagem.
  • A multa aparece com duas casas decimais, e a leitora Júlia, que tem os três problemas, recebe só o motivo do cadastro.
código inicial
# leitores.py: regras de empréstimo com and, not e elif.
LIMITE_LIVROS = 3


def avaliar(nome, ativo, multa, livros):
    pass  # libere ou mostre o motivo da recusa


avaliar("Helena", True, 0, 1)
avaliar("Otávio", False, 0, 0)
avaliar("Renata", True, 4.5, 2)
avaliar("Caio", True, 0, 3)
avaliar("Júlia", False, 2.0, 3)
saída esperada
Helena: empréstimo liberado
Otávio: recusado (cadastro inativo)
Renata: recusado (multa pendente de R$ 4.50)
Caio: recusado (limite de 3 livros atingido)
Júlia: recusado (cadastro inativo)
Ver dica

Teste primeiro o caso em que tudo está certo; nos elif seguintes, a ordem dos testes decide qual motivo aparece quando há mais de um problema.

Ver resposta
# leitores.py: regras de empréstimo com and, not e elif.
LIMITE_LIVROS = 3


def avaliar(nome, ativo, multa, livros):
    # Uma única condição com and reúne as três regras.
    if ativo and multa == 0 and livros < LIMITE_LIVROS:
        print(f"{nome}: empréstimo liberado")
    elif not ativo:
        print(f"{nome}: recusado (cadastro inativo)")
    elif multa > 0:
        print(f"{nome}: recusado (multa pendente de R$ {multa:.2f})")
    else:
        print(f"{nome}: recusado (limite de {LIMITE_LIVROS} livros atingido)")


avaliar("Helena", True, 0, 1)
avaliar("Otávio", False, 0, 0)
avaliar("Renata", True, 4.5, 2)
avaliar("Caio", True, 0, 3)
avaliar("Júlia", False, 2.0, 3)

Passo a passo

  1. LIMITE_LIVROS = 3 fica no topo, em maiúsculas: a regra aparece num lugar só e é reaproveitada na condição e na mensagem.
  2. if ativo and multa == 0 and livros < LIMITE_LIVROS: só é verdadeira quando as três partes são verdadeiras; basta uma falhar para o empréstimo não ser liberado.
  3. elif not ativo: inverte o bool: com ativo igual a False, not ativo é True e o motivo do cadastro é mostrado.
  4. elif multa > 0: só é avaliado para leitores ativos, porque os inativos já pararam no teste anterior.
  5. O else final dispensa uma condição: se o cadastro está ativo e não há multa, o único motivo que sobra é o limite de livros.
  6. {multa:.2f} mostra 4.5 como 4.50, no formato de dinheiro.
  7. Júlia tem cadastro inativo, multa e 3 livros, mas só o primeiro elif verdadeiro roda, por isso ela vê apenas o motivo do cadastro.

Por que funciona

O and resume as três regras numa pergunta só: "está tudo certo?". Quando a resposta é não, a cadeia de elif descobre o motivo testando os problemas na ordem de prioridade pedida, e a regra do primeiro bloco verdadeiro garante uma mensagem por leitor.

Como o and para no primeiro valor falso (avaliação em curto-circuito), o Python nem chega a olhar a multa de um leitor inativo nessa primeira condição.

Erros comuns

  • if ativo and multa == 0 or livros < 3:: o and é avaliado antes do or, e Otávio, inativo e sem livros, seria liberado. Use só and ou ponha parênteses deixando a intenção explícita.
  • elif ativo == False:: funciona, mas não é idiomático; linters como o Ruff apontam a comparação com False. Prefira not ativo.
  • Trocar a ordem para testar a multa antes do cadastro: Júlia passaria a ver o motivo da multa, contrariando o enunciado. A ordem dos elif é a ordem de prioridade.
  • if ativo and not multa and livros < 3: com multa = 0.0: funciona porque 0.0 é falso, mas esconde a regra; multa == 0 deixa claro o que está sendo testado.

Outra forma de resolver

Dá para testar os problemas primeiro e liberar no fim: if not ativo: ... elif multa > 0: ... elif livros >= LIMITE_LIVROS: ... else: print("liberado"). Essa forma evita a condição longa com and e é preferível quando há muitas regras; a versão com and deixa explícito, numa linha só, o que é preciso para ser liberado.

Saída esperada

Helena: empréstimo liberado
Otávio: recusado (cadastro inativo)
Renata: recusado (multa pendente de R$ 4.50)
Caio: recusado (limite de 3 livros atingido)
Júlia: recusado (cadastro inativo)

03Pontuação de uma rolagem de dadosDesafio

Escreva a função pontuar(d1, d2) para um jogo de dois dados: duplo seis vale 20 pontos, duplo um (olhos de cobra) vale 0, qualquer outra dupla vale a soma mais 5 e o resto vale a soma. A função devolve um texto com a paridade da soma, o nome da jogada, os pontos e se o jogador joga de novo (só com dados iguais e mais de 0 pontos).

↳ Requisitos
  • A jogada é escolhida com match (d1, d2):, com case (6, 6), case (1, 1), um case com guarda if a == b e case _.
  • A paridade (par ou ímpar) e o joga de novo/passa a vez são definidos com expressões condicionais.
  • pontuar() devolve o texto com return; quem imprime é a main().
  • main() só é chamada dentro de if __name__ == "__main__":.
código inicial
# dados.py: pontuação de uma rolagem de dois dados com match/case.


def pontuar(d1, d2):
    soma = d1 + d2
    # use match (d1, d2) para escolher pontos e nome da jogada
    return ""


def main():
    print(pontuar(6, 6))
    print(pontuar(1, 1))
    print(pontuar(4, 4))
    print(pontuar(2, 5))
    print(pontuar(3, 6))


if __name__ == "__main__":
    main()
saída esperada
6 e 6 (par): Duplo seis, 20 pontos, joga de novo
1 e 1 (par): Olhos de cobra, 0 pontos, passa a vez
4 e 4 (par): Dupla de 4, 13 pontos, joga de novo
2 e 5 (ímpar): Rolagem comum, 7 pontos, passa a vez
3 e 6 (ímpar): Rolagem comum, 9 pontos, passa a vez
Ver dica

Os padrões são testados de cima para baixo: os casos específicos (6 e 6, 1 e 1) precisam vir antes do case genérico de dupla, e o case _ sempre por último.

Ver resposta
# dados.py: pontuação de uma rolagem de dois dados com match/case.


def pontuar(d1, d2):
    soma = d1 + d2
    # match compara a tupla (d1, d2) com cada padrão, de cima para baixo.
    match (d1, d2):
        case (6, 6):
            pontos, nome = 20, "Duplo seis"
        case (1, 1):
            pontos, nome = 0, "Olhos de cobra"
        case (a, b) if a == b:  # guarda: só vale para dados iguais
            pontos, nome = soma + 5, f"Dupla de {a}"
        case _:
            pontos, nome = soma, "Rolagem comum"
    # Expressões condicionais: um valor ou outro, numa linha só.
    paridade = "par" if soma % 2 == 0 else "ímpar"
    proximo = "joga de novo" if d1 == d2 and pontos > 0 else "passa a vez"
    return f"{d1} e {d2} ({paridade}): {nome}, {pontos} pontos, {proximo}"


def main():
    print(pontuar(6, 6))
    print(pontuar(1, 1))
    print(pontuar(4, 4))
    print(pontuar(2, 5))
    print(pontuar(3, 6))


if __name__ == "__main__":
    main()

Passo a passo

  1. soma = d1 + d2 é calculada antes do match porque aparece em vários case e também na paridade.
  2. match (d1, d2): agrupa os dois dados numa tupla, e cada case descreve um formato possível dessa tupla.
  3. case (6, 6): e case (1, 1): são padrões literais: só casam com esses valores exatos. Cada um atribui pontos e nome numa atribuição múltipla.
  4. case (a, b) if a == b: captura os dados nas variáveis a e b e a guarda só aceita o padrão quando eles são iguais. Como os duplos seis e um já casaram antes, aqui só chegam as outras duplas.
  5. case _: é o curinga: qualquer rolagem que não casou com os padrões anteriores vale a soma simples.
  6. paridade = "par" if soma % 2 == 0 else "ímpar" escolhe um de dois textos numa linha, usando o resto da divisão por 2.
  7. proximo = "joga de novo" if d1 == d2 and pontos > 0 else "passa a vez" combina duas condições com and; olhos de cobra é dupla, mas tem 0 pontos e passa a vez.
  8. pontuar() devolve o texto com return e a main() o imprime, o que separa o cálculo da exibição.

Por que funciona

O match deixa cada regra do jogo num case próprio, testado de cima para baixo como uma cadeia de elif, mas descrevendo o formato do valor em vez de escrever comparações. A guarda acrescenta uma condição extra a um padrão, e o curinga garante que toda rolagem tenha uma pontuação.

As expressões condicionais completam o texto sem blocos extras: quando a tarefa é escolher entre dois valores, elas são mais diretas que um if/else que só atribui uma variável.

Erros comuns

  • Colocar case (a, b) if a == b: antes de case (6, 6):: o duplo seis casa com o padrão genérico e vale 17 em vez de 20. Os padrões específicos vêm primeiro.
  • case _: no início do match: o Python acusa SyntaxError: wildcard makes remaining patterns unreachable. O curinga é sempre o último.
  • case (d1, d1): para detectar dupla: dá SyntaxError: multiple assignments to name 'd1' in pattern, porque um padrão não pode capturar o mesmo nome duas vezes. Capture (a, b) e compare na guarda.
  • proximo = "joga de novo" if d1 == d2 else "passa a vez": olhos de cobra ganharia outra jogada. Inclua and pontos > 0 na condição.

Outra forma de resolver

Antes do Python 3.10, a mesma lógica era escrita com if d1 == 6 and d2 == 6: ... elif d1 == 1 and d2 == 1: ... elif d1 == d2: ... else: .... Essa forma ainda é a melhor quando as condições são faixas ou cálculos; o match brilha quando você compara o formato de um valor (tuplas, textos fixos, várias opções com |), como nas jogadas de dados.

Saída esperada

6 e 6 (par): Duplo seis, 20 pontos, joga de novo
1 e 1 (par): Olhos de cobra, 0 pontos, passa a vez
4 e 4 (par): Dupla de 4, 13 pontos, joga de novo
2 e 5 (ímpar): Rolagem comum, 7 pontos, passa a vez
3 e 6 (ímpar): Rolagem comum, 9 pontos, passa a vez

Últimas lições

Ver o arquivo completo →