Condições e ciclos

Comparações, decisões, for, while, acumuladores, limites e terminação.

TLDR

Perguntar sobre esta página

ChatGPTClaudePerplexityGrokGeminiCopiar e abrirDeepSeekCopiar e abrir

Comparar e combinar condições

Com nota = 10, a condição nota >= 10 é verdadeira, enquanto com nota = 9 é falsa; a condição escolhe instruções e o ciclo repete-as, podendo alterar o estado, isto é, os valores associados aos nomes, em cada iteração.

==, !=, <, <=, > e >= comparam valores. Para verificar se uma nota está entre 0 e 20, incluindo os extremos, podes escrever 0 <= nota <= 20. Não uses is para comparar números ou texto: is pergunta se tens o mesmo objeto.

not p nega uma condição; p and q exige ambas; p or q exige pelo menos uma. A ordem de precedência é not, and, or, mas parênteses tornam a intenção explícita.

Numa condição, False, None, zero e coleções vazias contam como falso. Os restantes valores destes tipos contam como verdadeiro. Por exemplo, if texto: testa se uma string não está vazia; não testa se contém a palavra "True".

Python avalia and e or com curto-circuito. Em divisor != 0 and total / divisor > 2, a divisão só ocorre quando o divisor é diferente de zero.

Estes operadores devolvem um dos operandos, não necessariamente bool: "" or "sem nome" vale "sem nome". Nas condições iniciais, usa comparações que produzam True ou False.

Escolher um ramo

Uma cadeia if / elif / else escolhe no máximo um ramo, o primeiro cuja condição é verdadeira. Dois if separados podem executar ambos. A indentação define o corpo; usa quatro espaços de forma consistente.

Classificar uma nota
nota = int(input())
if not 0 <= nota <= 20:
    print("inválida")
elif nota >= 10:
    print("aprovado")
else:
    print("reprovado")
Resultado

Executa o código para ver a saída e os gráficos.

A entrada 10 passa a validação e escolhe o segundo ramo, por isso o programa escreve aprovado. Testa 9, 10, 20 e 21 para verificar as fronteiras, onde um > no lugar de >= costuma mudar o resultado.

Ciclos for e a função range

for percorre os elementos de um iterável, um objeto que fornece valores um a um.

range(inicio, fim, passo) fornece inteiros até ao limite fim, que fica excluído. Omitir o início usa 0; omitir o passo usa 1. O passo não pode ser zero.

ChamadaProduzPorquê
range(1, 5)1, 2, 3, 4Conta de 1 até antes de 5
range(5, 0, -2)5, 3, 1Desce de 2 em 2 sem atingir 0
range(5, 0)VazioPasso 1 com início acima do fim

sum soma os valores de um iterável.

Para somar os quadrados dos inteiros de 1 até n, inicializamos um acumulador com zero e acrescentamos um termo em cada iteração. Para estes números, soma += k * k abrevia soma = soma + k * k: calcula o novo total e volta a associá-lo a soma.

Somar quadrados
n = int(input())
soma = 0
for k in range(1, n + 1):
    soma += k * k
print(soma)
Resultado

Executa o código para ver a saída e os gráficos.

ksoma antesTermo acrescentadosoma depois
1011
2145
35914
4141630

Depois de tratar k, a soma contém os quadrados de 1 até k. Esta propriedade é um invariante do ciclo e explica o resultado. Se n é zero, não há iterações e a soma vazia vale zero. Para um produto, o valor inicial costuma ser 1, porque multiplicar por zero destruiria o resultado.

Ciclos while e terminação

while testa a condição antes de cada iteração. Pode executar zero vezes. Usa-o quando o fim depende dos dados ou de uma condição que muda durante o cálculo.

Extrair e somar dígitos
n = int(input())
soma = 0
while n > 0:
    soma += n % 10
    n //= 10
print(soma)
Resultado

Executa o código para ver a saída e os gráficos.

n % 10 extrai o último dígito e n // 10 elimina-o; n //= 10 guarda esse quociente em n para avançar para o prefixo seguinte. A tabela acompanha a entrada 3083 passo a passo:

n antesDígito n % 10soma depoisn depois
308333308
30881130
300113
33140

O dígito zero mantém a soma, mas não termina o ciclo: ainda resta o prefixo 3. A paragem depende de n == 0, depois de retirar todos os dígitos.

Para n > 0, o quociente inteiro por 10 é menor que n e continua não negativo, por isso chega a zero. Sem a atualização de n, a condição continuaria verdadeira.

Este algoritmo assume entrada não negativa. Para aceitar inteiros negativos, usa n = abs(n) antes do ciclo. Para a entrada zero, a soma permanece zero, que é o resultado pretendido.

Construir um número a partir dos dígitos

Para inverter um inteiro não negativo sem o converter em texto, retiramos os seus dígitos da direita para a esquerda e colocamo-los no fim de outro inteiro. Em resultado * 10 + digito, multiplicar por 10 abre a posição das unidades; a adição ocupa essa posição com o dígito seguinte.

n = 1204
resultado = 0
while n > 0:
    resultado = resultado * 10 + n % 10
    n //= 10
print(resultado)

A saída é 4021. O estado permite conferir onde fica o zero:

Prefixo antesDígitoResultado depois
120444
120040
122402
114021

Para 1200, o resultado é 21: zeros à esquerda não fazem parte da representação de um inteiro. Se o contrato exigir conservar quatro posições, precisamos de texto ou de guardar também o comprimento. Para zero, o ciclo não executa e o resultado inicial zero já é correto.

A divisão com resto também permite mudar de base. Para escrever 13 em base 2, as divisões sucessivas produzem os restos 1, 0, 1 e 1. O primeiro resto é o dígito menos significativo, por isso a representação lê-se na ordem inversa, 1101. Conferimos com 1×23+1×22+0×2+1=131\times2^3+1\times2^2+0\times2+1=13. Em base b, usamos n % b e n // b, exigindo um inteiro b >= 2.

Sentinelas, break, continue e else

Uma sentinela marca o fim dos dados e não deve ser tratada como uma entrada normal. Se zero termina uma sequência de medições positivas, testa-o antes de o acrescentar à soma.

soma = 0
n = int(input())
while n != 0:
    if n > 0:
        soma += n
    n = int(input())
print(soma)

Com entradas 3, 5 e 0, a soma passa por 0, 3 e 8; o zero termina o ciclo sem ser somado. Sem a leitura nova no fim do corpo, o ciclo repetiria a primeira medição.

break sai do ciclo mais interno. continue passa à próxima iteração; num while, confirma que não salta a atualização necessária à terminação. O else de um ciclo corre quando o percurso termina sem break, mesmo que não tenha havido iterações.

for divisor in range(2, 7):
    if 7 % divisor == 0:
        print("composto")
        break
else:
    print("primo")

O exemplo escreve primo, porque nenhum divisor interrompe o ciclo, e o else está alinhado com for, não com if. Ao alterar 7, altera também o limite se pretenderes testar todos os divisores próprios; a lição de funções separa esse cálculo da entrada.

Escolher o percurso

Percorre valores diretamente quando só precisas deles; usa índices quando precisas de uma posição e enumerate quando precisas de ambos. Num ciclo aninhado, o corpo interior executa para cada valor do exterior.

for linha in range(2):
    for coluna in range(3):
        print(linha, coluna)

Os pares visitados são (0, 0), (0, 1), (0, 2), (1, 0), (1, 1) e (1, 2): seis, não cinco. Se há três linhas e quatro colunas, visitas 12 pares, não sete.

Exercícios

Diagnosticar a ordem dos ramos

Prevê a saída para nota = 16. Corrige a ordem para escrever bom nas notas de 15 a 20 e aprovado nas de 10 a 14. Assume uma nota válida de 0 a 20. Explica o que aconteceria se substituísses elif por outro if.

if nota >= 10:
    print("aprovado")
elif nota >= 15:
    print("bom")
else:
    print("reprovado")

Pista
Uma condição mais geral pode impedir a avaliação da mais restrita.
Solução

Para 16, o primeiro teste é verdadeiro e a saída é aprovado; o elif nem é avaliado. A correção testa primeiro nota >= 15, depois nota >= 10. Para 9, ambos falham e corre o else; para 10, só o segundo ramo é escolhido; para 15, o primeiro.

Com dois if independentes na versão original, 16 satisfaz ambos e escreve aprovado e bom. Nesse código, o else pertence ao segundo if, por isso 10 escreveria aprovado e depois reprovado.

Confere a tua resposta:

  • Previ aprovado para 16.
  • Pus o teste mais restrito primeiro.
  • Distingui uma cadeia de dois if independentes.
Voltar à explicação
Evitar uma divisão inválida

Para d = 0, d != 0 and 10 / d > 2 lança uma divisão por zero?

A tua resposta

Pista
and pode dispensar o segundo operando.
Mais uma pista

O primeiro operando vale False.

Solução

Não. O resultado é False e a divisão não executa. Inverter a ordem dos operandos perderia esta proteção.

  • Sim, dá ZeroDivisionError. A divisão não chega a ser avaliada.
  • Não, dá True. O primeiro operando é falso, logo a conjunção é falsa.
  • Não, dá False. and termina quando o primeiro operando é falso.

Erros frequentes

Assumir que todas as subexpressões de uma condição executam sempre.
Voltar à explicação
Seguir um range

Quanto vale sum(range(7, 0, -2))?

Pista
O limite zero fica excluído.
Mais uma pista
Os valores são 7, 5, 3 e 1.
Solução
7 + 5 + 3 + 1 = 16. O passo negativo aproxima-se do limite inferior.

Erros frequentes

Incluir zero ou esperar que o passo seja positivo.
Voltar à explicação
Distinguir dígito zero de prefixo zero

Segue este programa para n = 4072: indica o dígito extraído, o prefixo restante e a soma em cada iteração. Um colega propõe parar quando n % 10 == 0. Que resultado obteria e por que está errado?

soma = 0
while n > 0:
    soma += n % 10
    n //= 10
print(soma)

Pista
Em 40, o último dígito é zero, mas ainda falta tratar o 4.
Solução
n antesDígitoPrefixo depoisSoma depois
407224072
4077409
40049
44013

O ciclo correto termina no prefixo zero e escreve 13. Parar no dígito zero terminaria em 40 com soma 9, perdendo o 4. A medida de progresso é o inteiro não negativo n, que diminui por divisão inteira em cada iteração.

Confere a tua resposta:

  • Segui os prefixos 4072, 407, 40, 4 e 0.
  • Obtive soma 13.
  • Expliquei por que parar num dígito zero dá 9.
Voltar à explicação
Distinguir encontrar de esgotar a procura

Prevê a saída para valores = [2, -1, 4], depois [2, 0, 4] e finalmente []. Um colega substitui break por continue. Que saída terá agora a primeira lista e por que já não resolve a mesma procura?

for valor in valores:
    if valor < 0:
        print("encontrado")
        break
else:
    print("nenhum")

Solução

Com [2, -1, 4], escreve encontrado e sai por break, sem executar o else. Com [2, 0, 4], percorre tudo sem negativo e escreve nenhum. Com [], também esgota o percurso sem break e escreve nenhum.

Substituindo por continue, o -1 ainda escreve encontrado, mas só salta o resto dessa iteração. O percurso continua com 4 e acaba normalmente, executando else: escreve também nenhum. O else não pergunta se houve iterações ou se a condição do if alguma vez foi verdadeira; pergunta se o ciclo terminou normalmente, sem break.

Confere a tua resposta:

  • Previ encontrado só quando existe um negativo.
  • Previ nenhum tanto sem negativos como na lista vazia.
  • Expliquei que break impede else.
Voltar à explicação
Somar com limites inclusivos

Lê um inteiro n não negativo e escreve a soma dos múltiplos positivos de 3 entre 1 e n, incluindo n se for múltiplo de 3. Para n = 10, somas 3 + 6 + 9 = 18. Usa um ciclo para praticar o acumulador.

Python
n = int(input())
total = 0
print(total)
Testes e resultado

Verifica o código para comparar o resultado com os testes.

Testes
  1. Sem termos
    Entrada
    0
    Esperado:
    0
  2. Antes do primeiro múltiplo
    Entrada
    2
    Esperado:
    0
  3. Limite incluído
    Entrada
    3
    Esperado:
    3
  4. Vários termos
    Entrada
    10
    Esperado:
    18
  5. Outro limite incluído
    Entrada
    12
    Esperado:
    30

Pista

Começa a soma em zero. O último valor permitido é n.

Mais uma pista

Podes percorrer range(3, n + 1, 3), ou percorrer todos os inteiros e testar o resto.

Solução

O passo 3 visita só os múltiplos. O limite n + 1 permite incluir n. Quando n é menor que 3, o percurso é vazio e o total permanece zero.

n = int(input())
total = 0
for valor in range(3, n + 1, 3):
    total += valor
print(total)

Erros frequentes

Excluir n com range(3, n, 3), imprimir dentro do ciclo ou esquecer a inicialização.

Voltar à explicação
Somar até à sentinela

Define soma_ate_zero(valores): soma todos os valores até ao primeiro zero, incluindo negativos, sem incluir a sentinela nem o que vem depois. Ao contrário do exemplo da lição, que filtra só positivos, aqui cada valor antes do zero conta.

Python
def soma_ate_zero(valores):
    return 0
Testes e resultado

Verifica o código para comparar o resultado com os testes.

Testes
  1. Dois valores
    Código do teste
    print(soma_ate_zero([3, 5, 0, 9]))
    Esperado:
    8
  2. Zero imediato
    Código do teste
    print(soma_ate_zero([0]))
    Esperado:
    0
  3. Sem resto
    Código do teste
    print(soma_ate_zero([4, 0]))
    Esperado:
    4
  4. Negativos incluídos
    Código do teste
    print(soma_ate_zero([3, -2, 0, 9]))
    Esperado:
    1
  5. Só negativos
    Código do teste
    print(soma_ate_zero([-4, -1, 0]))
    Esperado:
    -5

Pista

Para no zero antes de somar.

Mais uma pista

Um filtro if valor &gt; 0 copiado da lição chumba o teste com negativos: [3, -2, 0] deve dar 1, não 3. Soma cada valor antes do zero sem filtrar.

Solução

Percorre a lista e interrompe no zero. Para [3, 5, 0, 9], a soma passa por 0, 3 e 8. Para [3, -2, 0, 9], passa por 0, 3 e 1.

def soma_ate_zero(valores):
    soma = 0
    for valor in valores:
        if valor == 0:
            break
        soma += valor
    return soma

Erros frequentes

Somar o zero da sentinela; continuar a somar depois do zero; filtrar só positivos e ignorar negativos.

Voltar à explicação
Construir uma representação noutra base

Define representar(n, base): recebe um inteiro não negativo e uma base inteira de 2 a 10, incluindo os extremos. Devolve uma string com a representação de n nessa base, sem zeros à esquerda, exceto o próprio zero, que se representa por "0". Usa divisões sucessivas com resto. Justifica por que a ordem dos restos difere da ordem dos dígitos no resultado.

Python
def representar(n, base):
    return ""
Testes e resultado

Verifica o código para comparar o resultado com os testes.

Testes
  1. Zero tem um dígito
    Código do teste
    print(repr(representar(0, 2)))
    Esperado:
    '0'
  2. Restos por ordem inversa
    Código do teste
    print(repr(representar(13, 2)))
    Esperado:
    '1101'
  3. Zeros interiores
    Código do teste
    print(repr(representar(100, 10)))
    Esperado:
    '100'
  4. Outra base
    Código do teste
    print(repr(representar(46, 7)))
    Esperado:
    '64'
  5. Um dígito
    Código do teste
    print(repr(representar(5, 6)))
    Esperado:
    '5'

Pista
O primeiro resto é o dígito das unidades, independentemente da base.
Solução

Cada resto fica entre zero e base - 1, portanto cabe num único carácter decimal para as bases permitidas. Retiramos esse dígito do prefixo e acrescentamo-lo à esquerda do texto já construído.

def representar(n, base):
    if n == 0:
        return "0"
    resultado = ""
    while n > 0:
        resultado = str(n % base) + resultado
        n //= base
    return resultado

Para 46 em base 7, o primeiro resto é 4 e o quociente 6; o segundo resto é 6 com quociente zero. O texto final é "64", pois 6×7+4=466\times7+4=46. A medida n diminui quando é positiva porque a base é pelo menos 2. Sem o caso de zero, a função devolveria uma string vazia. Concatenar os restos à direita daria a ordem errada para 13 em base 2, "1011".

Voltar à explicação

À tua maneira

Aparência

Modo de cor
Tema
Cor de destaque

Leitura

Fonte de leitura

Álgebra, lógica e uma ideia de cada vez.

Código

Fonte do código

Navegação

Cursor de leitura, sem edição. h, j, k, l movem; / pesquisa nesta página. v seleciona caracteres; V seleciona linhas; y copia. Tab permite destacar ou comentar. Espaço ou Enter abre blocos recolhíveis. Nos cartões, h, j, k, l mudam o foco.

CSS personalizado

Ativa uma sugestão ou guarda o teu CSS. Só muda este navegador.

Usa --page, --text e --accent para acompanhar o tema.

Seletores e recuperação

.site-header, .prose, .course-card, [data-reading-history], [data-playground] e .page-actions.

Abre a aparência com a tecla vírgula ou no rodapé. Se o CSS esconder os controlos, abre esta página sem CSS personalizado.

Pesquisar

Escreve para pesquisar em todo o site.

para escolher · Enter para abrir · Esc para fechar

Copiar fórmula

A cópia automática não está disponível. Copia o LaTeX abaixo.

Pesquisar nesta página

Enter procura · n / N repetem · Esc cancela. Ctrl / Cmd K pesquisa todo o site.

Atalhos de teclado

Clica numa tecla para a mudar. Esc cancela. Backspace desativa.

PesquisarCtrl / Cmd K

Os atalhos não interferem enquanto escreves. Tab e Enter funcionam sempre.