Curso de Python / Escolher caminhos com if, elif e else

Uma sequência if, elif e else escolhe um caminho de execução testando condições de cima para baixo. Somente o primeiro ramo correspondente é executado; por isso, a ordem dos testes e a inclusão dos limites precisam fazer parte do planejamento.

Use a indentação para definir cada ramo

A condição termina com dois-pontos, e as instruções desse ramo ficam indentadas. Use uma profundidade consistente, convencionalmente quatro espaços, para todas as instruções do mesmo bloco. Evite misturar tabulações e espaços, pois a aparência no editor pode não refletir a estrutura interpretada por Python.

elif acrescenta outro teste à mesma sequência. else não recebe uma condição: ele será usado quando nenhum dos testes anteriores for verdadeiro. Uma cadeia pode funcionar sem else, mas nesse caso é possível que nenhum de seus ramos seja executado. O tutorial oficial de controle de fluxo apresenta essa estrutura.

Duas instruções if independentes podem executar dois blocos. Em uma cadeia if–elif, a primeira correspondência encerra a escolha. Use a cadeia para categorias mutuamente exclusivas e testes separados quando cada condição deva ser verificada de forma independente.

Execute uma classificação completa de valores

Salve o código abaixo em UTF-8 como classify.py, na pasta do projeto. Execute python classify.py no ambiente selecionado; no macOS ou Ubuntu, fora de um ambiente virtual, use python3 se esse for o nome do interpretador. Não são necessários pacotes ou arquivos externos.

amount = 8000
if amount < 0:
    label = "invalid"
elif amount == 0:
    label = "free"
elif amount <= 10000:
    label = "small"
else:
    label = "large"
print(label)

A saída esperada é:

small

Com amount = 8000, os testes de valor negativo e de zero são falsos. O teste amount <= 10000 é verdadeiro e atribui "small" a label. O ramo else não é executado. O print(label) está fora da cadeia e mostra o resultado já escolhido.

Os rótulos em inglês são os dados deste exercício: invalid significa inválido, free indica zero, small indica a faixa pequena e large a faixa maior. Esses limites são uma regra didática do programa, não uma classificação universal de despesas.

Defina as faixas e confira os limites

Considerando valores inteiros, o programa separa negativos, zero, valores de 1 a 10000 e valores acima de 10000. Os primeiros testes eliminam os casos antes que os posteriores sejam considerados. Se o teste amplo amount <= 10000 viesse primeiro, ele também aceitaria negativos e zero, impedindo a classificação específica desses casos.

Valor de amount Rótulo esperado
-1 invalid
0 free
1 ou 10000 small
10001 large

A classificação pressupõe um valor numérico e não valida o tipo de uma entrada externa. Converter o texto recebido e tratar uma conversão inválida são etapas distintas, mostradas na aula de entrada e saída. Não compare diretamente uma string como "8000" com os limites numéricos.

A aula de comparações e operadores lógicos explica como combinar testes. Aqui, a questão adicional é a ordem de execução: uma condição pode ser correta isoladamente e, ainda assim, ficar inacessível por causa de uma condição anterior.

Mantenha os valores definidos em todos os caminhos

Uma variável usada depois da cadeia precisa ter recebido um valor em todo caminho que chegar até esse uso. Se você atribuir result somente quando uma condição for verdadeira, um caminho falso poderá terminar com um nome inexistente. Defina um padrão antes do teste, quando houver um padrão válido, ou atribua nos dois caminhos com if e else.

No nível do módulo, ler um nome que não foi definido pode provocar NameError. Dentro de uma função, uma atribuição faz normalmente o nome ser local; ler esse nome antes de ele receber um valor em determinado caminho pode provocar UnboundLocalError. A referência de resolução de nomes explica a diferença. Não basta testar somente um caso em que a atribuição aconteceu.

  1. Substitua o valor inicial de amount por cada entrada da tabela, uma por execução, e confira o rótulo correspondente.
  2. Use amount = 10000 e altere somente o teste amount <= 10000 para amount < 10000. O rótulo passa de small para large.
  3. Restaure <= e amount = 8000. Confirme novamente small.
  4. Ao planejar duas advertências independentes, pergunte se as duas devem aparecer quando ambas as condições forem verdadeiras. Se sim, dois if separados podem representar a regra melhor que uma cadeia exclusiva.

Se um ramo parecer nunca executar, examine os testes anteriores antes de acrescentar mais níveis de indentação. Casos próximos aos limites e caminhos em que uma variável não é atribuída costumam revelar mais problemas do que repetir apenas um valor intermediário.