11. Repetindo Ações com Loops while
Programas muitas vezes precisam repetir ações várias vezes. Você já viu como tomar decisões com instruções if no Capítulo 8, mas e se você precisar executar uma ação repetidamente até que uma determinada condição seja atendida? É aqui que os loops entram.
Python oferece dois tipos principais de loops: loops while e loops for. Neste capítulo, vamos focar nos loops while, que repetem um bloco de código enquanto uma condição permanecer verdadeira. O loop for, que é mais adequado para iterar sobre sequências, será abordado no Capítulo 12.
Entender loops while é fundamental para escrever programas que conseguem processar dados repetidamente, validar entrada do usuário, implementar loops de jogos e lidar com muitos outros cenários reais de programação.
11.1) A Estrutura de um Loop while
Um loop while executa repetidamente um bloco de código enquanto uma condição especificada for avaliada como True. Assim que a condição se torna False, o loop para, e o programa continua com o código após o loop.
Sintaxe Básica de um Loop while
A estrutura de um loop while se parece com isto:
while condition:
# Bloco de código para repetir
# Este código roda enquanto condition for TrueA condition é qualquer expressão que resulta em um valor booleano (ou pode ser interpretada como truthy ou falsy, como aprendemos no Capítulo 7). O bloco de código indentado abaixo da instrução while é chamado de corpo do loop, e ele executa repetidamente enquanto a condição permanecer True.
Vamos ver um exemplo simples:
# Contar de 1 a 5
count = 1
while count <= 5:
print(f"Count is: {count}")
count = count + 1 # Incrementar count
print("Loop finished!")Output:
Count is: 1
Count is: 2
Count is: 3
Count is: 4
Count is: 5
Loop finished!Como isso funciona passo a passo:
- Inicializamos
countcom1 - A condição
count <= 5é verificada. Como1 <= 5éTrue, o corpo do loop executa - Dentro do loop, imprimimos o contador atual e então incrementamos ele em 1
- Depois que o corpo do loop termina, o Python retorna à instrução
whilee verifica a condição novamente - Esse processo se repete até
countse tornar6, momento em que6 <= 5éFalse, e o loop termina - O programa continua com o código após o loop
A sacada principal é que a condição é verificada antes de cada iteração (cada repetição do corpo do loop). Se a condição for False inicialmente, o corpo do loop nunca executa:
count = 10
while count <= 5:
print("This will never print")
print("Loop skipped entirely")Output:
Loop skipped entirelyComo 10 <= 5 é False desde o início, o corpo do loop nunca roda.
A Importância de Modificar a Variável do Loop
Para um loop while eventualmente parar, alguma coisa dentro do loop precisa mudar a condição de True para False. Isso normalmente significa modificar a(s) variável(is) usada(s) na condição. Se você esquecer de fazer isso, você cria um loop infinito (que vamos discutir em detalhes na próxima seção).
Aqui vai um exemplo que demonstra por que atualizar a variável do loop importa:
# Calcular a soma dos números de 1 a 10
total = 0
number = 1
while number <= 10:
total = total + number # Somar o número atual ao total
number = number + 1 # Ir para o próximo número
print(f"The sum of numbers from 1 to 10 is: {total}")Output:
The sum of numbers from 1 to 10 is: 55Neste exemplo, estamos acumulando uma soma enquanto avançamos pelos números. Tanto total quanto number mudam a cada iteração, mas é a modificação de number que garante que o loop eventualmente termine quando number se tornar 11.
Loops while com Entrada do Usuário
Um uso prático de loops while é processar entrada do usuário até que uma condição específica seja atendida. Vamos criar um jogo simples de adivinhação de número:
# Jogo simples de adivinhação de número
secret_number = 7
guess = 0
while guess != secret_number:
guess = int(input("Guess the number (1-10): "))
if guess < secret_number:
print("Too low! Try again.")
elif guess > secret_number:
print("Too high! Try again.")
else:
print("Correct! You guessed it!")Esse loop continua pedindo palpites até o usuário digitar o número correto. Cada iteração processa um palpite e dá feedback. O loop termina naturalmente quando guess é igual a secret_number, fazendo a condição guess != secret_number se tornar False.
Loops while com Múltiplas Condições
Você pode usar operadores booleanos (and, or, not) para criar condições de loop mais complexas, como aprendemos no Capítulo 9:
# Processar entrada até o usuário digitar "quit" ou chegar a 5 tentativas
attempts = 0
user_input = ""
while user_input != "quit" and attempts < 5:
user_input = input("Enter a command (or 'quit' to exit): ")
attempts += 1
if user_input == "quit":
print("Goodbye!")
else:
print(f"You entered: {user_input}")
print(f"Attempts remaining: {5 - attempts}")
if attempts >= 5 and user_input != "quit":
print("Maximum attempts reached.")Esse loop continua enquanto ambas as condições forem verdadeiras: o usuário não digitou "quit" e não passou de 5 tentativas. O loop termina quando qualquer condição se tornar falsa.
Visualizando a Execução de um Loop while
Aqui vai um fluxograma mostrando como um loop while executa:
O loop cria um ciclo em que a condição é verificada, o corpo executa se a condição for verdadeira, as variáveis são atualizadas e então a condição é verificada novamente. Esse ciclo continua até que a condição se torne falsa.
11.2) Loops Infinitos e Como Evitá-los
Um loop infinito é um loop que nunca termina porque sua condição nunca se torna False. Loops infinitos são um dos erros mais comuns que iniciantes cometem com loops while, e eles podem fazer seu programa travar indefinidamente.
O que Causa Loops Infinitos?
A causa mais comum de loops infinitos é esquecer de modificar a(s) variável(is) que afetam a condição do loop. Vamos ver um exemplo problemático:
# AVISO: Loop infinito - apenas para demonstração
# PROBLEMA: count nunca é modificado
count = 1
while count <= 5:
print(f"Count is: {count}")
# Missing: count += 1Se você executasse esse código, ele imprimiria "Count is: 1" para sempre porque count permanece 1, e 1 <= 5 é sempre True. A condição nunca muda.
Como reconhecer que isso é um loop infinito: Olhe a condição do loop (count <= 5) e então verifique se algo dentro do corpo do loop modifica count. Se não, e a condição começa como True, você tem um loop infinito.
Aqui está a versão corrigida:
# Versão correta com incremento adequado
count = 1
while count <= 5:
print(f"Count is: {count}")
count += 1 # Isso garante que o loop eventualmente termineOutput:
Count is: 1
Count is: 2
Count is: 3
Count is: 4
Count is: 5Fazendo Debug de Loops Infinitos com Limites de Segurança
Ao desenvolver código com loops, é útil adicionar um limite de segurança para evitar loops infinitos acidentais durante os testes:
# Limite de segurança durante o desenvolvimento
count = 1
iterations = 0
max_iterations = 100 # Limite de segurança
while count <= 5 and iterations < max_iterations:
print(f"Count is: {count}")
count += 1
iterations += 1
if iterations >= max_iterations:
print("WARNING: Maximum iterations reached. Check for infinite loop.")Esse padrão adiciona um contador que rastreia quantas vezes o loop executou. Se ele alcançar o limite de segurança, você sabe que algo está errado na sua lógica do loop. Quando você estiver confiante de que seu loop funciona corretamente, você pode remover o limite de segurança.
Loops Infinitos com Entrada do Usuário
Outro cenário comum para loops infinitos envolve validação de entrada do usuário:
# AVISO: Possível loop infinito - apenas para demonstração
# PROBLEMA: Se o usuário nunca digitar uma entrada válida, o loop nunca termina
age = -1
while age < 0:
age = int(input("Enter your age: "))
# Se o usuário digitar um número negativo, o loop continuaEsse loop funciona corretamente se o usuário eventualmente digitar um número não negativo, mas vira um loop infinito se o usuário continuar digitando valores negativos. Embora isso possa ser aceitável para alguns programas (você quer continuar pedindo até receber uma entrada válida), é importante entender que a finalização do loop depende totalmente do comportamento do usuário.
Uma abordagem mais robusta poderia incluir uma forma de sair:
# Melhor abordagem com opção de saída
age = -1
while age < 0:
user_input = input("Enter your age (or 'quit' to exit): ")
if user_input.lower() == 'quit':
print("Exiting program.")
age = 0 # Definir um valor válido para sair do loop
else:
age = int(user_input)
if age < 0:
print("Age must be non-negative. Please try again.")
if age > 0:
print(f"Your age is: {age}")Loops Infinitos com Erros Lógicos
Às vezes, loops infinitos acontecem por causa de erros lógicos em como você atualiza variáveis:
# AVISO: Loop infinito - apenas para demonstração
# PROBLEMA: count é decrementado em vez de incrementado
count = 1
while count <= 5:
print(f"Count is: {count}")
count -= 1 # ERRO: Isso deixa count menor, não maiorIsso cria um loop infinito porque count começa em 1 e vira 0, -1, -2, etc. Como números negativos são sempre menores ou iguais a 5, a condição count <= 5 permanece True para sempre.
A versão corrigida:
count = 1
while count <= 5:
print(f"Count is: {count}")
count += 1 # Correto: incrementar para eventualmente passar de 5Fazendo Debug de Loops Infinitos
Se você acidentalmente criar um loop infinito ao executar um script Python, você pode pará-lo apertando Ctrl+C (ou Cmd+C no Mac) no seu terminal. Isso envia um sinal de interrupção de teclado para o Python, que para o programa.
Como evitar loops infinitos:
- Sempre garanta que a condição do loop pode se tornar False: Verifique que variáveis na condição são modificadas dentro do loop
- Use o operador de comparação correto: Garanta que
<=,<,!=, etc., correspondem à sua intenção - Teste com valores pequenos primeiro: Antes de rodar um loop que pode executar muitas vezes, teste com limites pequenos
- Adicione instruções print de debug: Imprima temporariamente a variável do loop para ver como ela muda:
- Use limites de segurança durante o desenvolvimento: Como mostrado antes, adicione um contador máximo de iterações enquanto testa
11.3) Usando break e continue em Loops while
Python fornece duas instruções especiais que te dão mais controle sobre a execução do loop: break e continue. Essas instruções permitem que você altere o fluxo normal de um loop com base em condições que surgem durante a execução.
11.3.1) A Instrução break
A instrução break encerra imediatamente o loop, independentemente da condição do loop. Quando o Python encontra break, ele sai totalmente do loop e continua com o código após o loop.
Aqui vai um exemplo simples:
# Sair do loop quando um valor específico for alcançado
count = 1
while count <= 10:
if count == 5:
print("Reached 5, stopping loop")
break
print(f"Count: {count}")
count += 1
print("Loop exited")Output:
Count: 1
Count: 2
Count: 3
Count: 4
Reached 5, stopping loop
Loop exitedPerceba que, quando count é igual a 5, a instrução break executa, e o loop termina imediatamente. O loop nunca chega em count = 6, mesmo que a condição count <= 10 ainda fosse True.
Como break Muda o Fluxo do Loop
Entender como break altera a execução normal do loop é crucial. Aqui vai um fluxograma mostrando a diferença:
O ponto principal: break fornece um caminho de saída imediata do loop, ignorando tanto o restante do código do corpo do loop quanto a verificação da condição.
Uso Prático de break: Validação de Entrada
Um dos usos mais comuns de break é sair de um loop quando uma entrada válida é recebida:
# Continuar pedindo uma entrada válida até receber
while True:
age_input = input("Enter your age (must be positive): ")
# Tentar converter para inteiro
try:
age = int(age_input)
# Verificar se é válido
if age > 0:
print(f"Thank you! Your age is {age}")
break # Sair do loop com entrada válida
else:
print("Age must be positive. Please try again.")
except ValueError:
print("That's not a valid number. Please try again.")
print("Input validation complete")Esse padrão usa while True: para criar um loop infinito intencional, e então usa break para sair quando uma entrada válida é recebida. Isso é mais limpo do que tentar gerenciar uma condição de loop complexa. (Nota: Estamos usando try e except aqui, que vamos aprender em detalhes na Parte VII. Por enquanto, apenas entenda que isso captura erros ao converter a entrada para um inteiro.)
break com Múltiplas Condições
Você pode usar break com condições complexas para sair de um loop quando qualquer um de vários critérios for atendido:
# Procurar um item específico na entrada do usuário
search_term = "python"
attempts = 0
max_attempts = 5
while attempts < max_attempts:
user_input = input("Enter a word (or 'quit' to exit): ").lower()
attempts += 1
if user_input == 'quit':
print("User requested exit")
break
if user_input == search_term:
print(f"Found '{search_term}'!")
break
print(f"'{user_input}' is not '{search_term}'. Try again.")
print(f"Attempts remaining: {max_attempts - attempts}")
if attempts >= max_attempts:
print("Maximum attempts reached")Esse loop pode terminar de três formas:
- O usuário digita "quit" (primeiro
break) - O usuário digita o termo de busca (segundo
break) - O máximo de tentativas é atingido (a condição do loop se torna
False)
11.3.2) A Instrução continue
A instrução continue ignora o restante da iteração atual e volta para a verificação da condição do loop. Diferente do break, que sai do loop totalmente, continue apenas pula para a próxima iteração.
Aqui vai um exemplo básico:
# Imprimir apenas números ímpares de 1 a 10
count = 0
while count < 10:
count += 1
if count % 2 == 0: # Se for número par
continue # Ignorar o resto e ir para a próxima iteração
print(f"Odd number: {count}")Output:
Odd number: 1
Odd number: 3
Odd number: 5
Odd number: 7
Odd number: 9Como isso funciona:
countincrementa no início de cada iteração- Se
countfor par (count % 2 == 0),continueexecuta - A instrução
continueignora oprinte volta para a condição dowhile - Se
countfor ímpar,continuenão executa, então oprintroda
Como continue Muda o Fluxo do Loop
Aqui vai um fluxograma mostrando como continue afeta a execução do loop:
A diferença crucial entre break e continue:
- break: Sai do loop completamente, pulando para o código após o loop
- continue: Ignora o código restante na iteração atual, volta para a verificação da condição
Nota Importante sobre a Posição do continue
Perceba que count += 1 vem antes do continue. Se colocássemos isso depois, números pares fariam o continue pular o incremento, criando um loop infinito:
# AVISO: Loop infinito - apenas para demonstração
# PROBLEMA: continue ignora o incremento para números pares
count = 0
while count < 10:
if count % 2 == 0:
continue # Ignora tudo abaixo, incluindo count += 1
count += 1 # ERRO: Isso nunca roda para números pares
print(f"Odd number: {count}")Quando count é 0 (par), continue executa, pulando count += 1. O loop verifica 0 < 10 de novo, e o ciclo se repete para sempre.
A regra: Sempre garanta que as variáveis do loop que afetam a condição sejam atualizadas antes de qualquer instrução continue que possa pular o restante do corpo do loop.
Uso Prático de continue: Filtrando Dados
A instrução continue é útil ao processar dados e você quer ignorar certos itens:
# Processar apenas notas válidas
score_count = 0
total_score = 0
attempts = 0
while attempts < 5:
score_input = input(f"Enter score {attempts + 1} (or 'skip' to skip): ")
attempts += 1
if score_input.lower() == 'skip':
print("Skipping this score")
continue # Ir para a próxima iteração
try:
score = int(score_input)
if score < 0 or score > 100:
print("Score must be between 0 and 100. Skipping.")
continue # Ignorar notas inválidas
# Nota válida - processar
total_score += score
score_count += 1
print(f"Score recorded: {score}")
except ValueError:
print("Invalid input. Skipping.")
continue
if score_count > 0:
average = total_score / score_count
print(f"\nAverage of {score_count} valid scores: {average:.1f}")
else:
print("\nNo valid scores entered")Este exemplo demonstra vários usos de continue:
- Pular quando o usuário digita "skip"
- Pular quando a nota está fora do intervalo válido
- Pular quando a entrada não é um número válido
Cada continue evita que a nota seja adicionada ao total, mas o loop continua para a próxima tentativa.
Combinando break e continue
Você pode usar tanto break quanto continue no mesmo loop para um controle mais sofisticado:
# Processar números até a soma passar de 100, ignorando números negativos
total = 0
count = 0
while True:
number_input = input("Enter a number (or 'done' to finish): ")
if number_input.lower() == 'done':
print("User finished entering numbers")
break # Sair do loop
try:
number = int(number_input)
if number < 0:
print("Negative numbers not allowed. Skipping.")
continue # Ir para a próxima iteração
total += number
count += 1
print(f"Added {number}. Current total: {total}")
if total > 100:
print("Total exceeded 100. Stopping.")
break # Sair do loop quando o limite for alcançado
except ValueError:
print("Invalid input. Skipping.")
continue
print(f"\nFinal total: {total} (from {count} numbers)")Esse loop demonstra:
breakpara sair quando o usuário digita "done"continuepara ignorar números negativoscontinuepara ignorar entrada inválidabreakpara sair quando o total passa de 100
11.4) Usando else com Loops while
Python tem um recurso único que muitas outras linguagens de programação não têm: você pode anexar uma cláusula else a um loop while. Esse bloco else executa apenas se o loop terminar normalmente (ou seja, a condição do loop se torna False sem encontrar uma instrução break).
Sintaxe Básica de else com while
A sintaxe se parece com isto:
while condition:
# Corpo do loop
else:
# Isso executa apenas se o loop terminar normalmente
# (não interrompido por break)Vamos ver um exemplo simples:
# Contar de 1 a 5 com cláusula else
count = 1
while count <= 5:
print(f"Count: {count}")
count += 1
else:
print("Loop completed normally")
print("Program continues")Output:
Count: 1
Count: 2
Count: 3
Count: 4
Count: 5
Loop completed normally
Program continuesO bloco else executa porque o loop rodou até sua condição (count <= 5) se tornar False. O loop terminou "normalmente" sem ser interrompido.
Quando else NÃO Executa: A Instrução break
O comportamento chave da cláusula else é que ela não executa se o loop for encerrado por uma instrução break:
# Procurar um número com break
count = 1
target = 3
while count <= 5:
print(f"Checking: {count}")
if count == target:
print(f"Found {target}!")
break
count += 1
else:
print("Target not found in range")
print("Search complete")Output:
Checking: 1
Checking: 2
Checking: 3
Found 3!
Search completePerceba que o bloco else ("Target not found in range") não executou porque o loop foi encerrado por break. Essa é a distinção crucial: else roda apenas quando o loop sai normalmente (a condição se torna False), não quando sai via break.
Agora vamos ver o que acontece quando o alvo não é encontrado:
# Procurar um número que não existe
count = 1
target = 7 # Não está no intervalo 1-5
while count <= 5:
print(f"Checking: {count}")
if count == target:
print(f"Found {target}!")
break
count += 1
else:
print("Target not found in range")
print("Search complete")Output:
Checking: 1
Checking: 2
Checking: 3
Checking: 4
Checking: 5
Target not found in range
Search completeDesta vez, o loop completou todas as iterações sem encontrar o alvo, então a condição count <= 5 eventualmente se tornou False, e o bloco else executou.
Como else Funciona com a Conclusão do Loop
Aqui vai um fluxograma mostrando os caminhos de execução com a cláusula else:
O bloco else só é alcançado quando a condição do loop se torna False naturalmente. Se break for encontrado, o fluxo pula diretamente o bloco else e vai para o código após o loop.
Uso Prático: Operações de Busca
A cláusula else é particularmente útil para operações de busca em que você quer saber se algo foi encontrado:
# Procurar uma senha válida em uma lista de tentativas
valid_password = "python123"
max_attempts = 3
attempts = 0
while attempts < max_attempts:
password = input(f"Enter password (attempt {attempts + 1}/{max_attempts}): ")
attempts += 1
if password == valid_password:
print("Access granted!")
break
else:
print("Access denied. Maximum attempts exceeded.")
print("Account locked.")Se o usuário digitar a senha correta, break executa e o bloco else é ignorado. Se todas as tentativas forem usadas sem sucesso, o loop termina normalmente e o bloco else executa, indicando falha.
else com continue
A instrução continue não impede que o bloco else execute. Apenas break faz isso:
# continue não afeta a execução do else
count = 0
while count < 5:
count += 1
if count == 3:
print(f"Skipping {count}")
continue # Ir para a próxima iteração
print(f"Processing {count}")
else:
print("Loop completed normally (continue doesn't prevent this)")Output:
Processing 1
Processing 2
Skipping 3
Processing 4
Processing 5
Loop completed normally (continue doesn't prevent this)O bloco else executa porque o loop terminou normalmente. A instrução continue afeta apenas iterações individuais, não a conclusão geral do loop.
Comparando else com e sem break
Vamos ver uma comparação lado a lado:
# Exemplo 1: Encontrando um número primo (com break)
print("Finding first number divisible by 7:")
number = 1
while number <= 20:
if number % 7 == 0:
print(f"Found: {number}")
break
number += 1
else:
print("No number divisible by 7 found in range")
print()
# Exemplo 2: Verificando todos os números (sem break)
print("Checking all numbers for divisibility by 7:")
number = 1
while number <= 20:
if number % 7 == 0:
print(f"Found: {number}")
number += 1
else:
print("Finished checking all numbers")Output:
Finding first number divisible by 7:
Found: 7
Checking all numbers for divisibility by 7:
Found: 7
Found: 14
Finished checking all numbersNo primeiro exemplo, break para o loop após encontrar a primeira correspondência, então else não executa. No segundo exemplo, o loop verifica todos os números e termina normalmente, então else executa.
Quando Usar else com Loops while
A cláusula else é mais útil quando:
- Operações de busca: Você quer saber se algo foi encontrado ou não
- Validação com tentativas limitadas: Você precisa lidar com o caso em que todas as tentativas se esgotam
- Processamento com saída antecipada: Você quer um comportamento diferente para "concluiu tudo" vs "parou antes"
No entanto, else com loops pode ser confuso para programadores vindo de outras linguagens (onde esse recurso não existe). Às vezes é mais claro usar uma variável flag:
# Usando cláusula else
attempts = 0
while attempts < 3:
password = input("Enter password: ")
attempts += 1
if password == "secret":
print("Access granted")
break
else:
print("Access denied")
# Equivalente usando uma variável flag (às vezes mais claro)
attempts = 0
access_granted = False
while attempts < 3:
password = input("Enter password: ")
attempts += 1
if password == "secret":
print("Access granted")
access_granted = True
break
if not access_granted:
print("Access denied")Ambas as abordagens funcionam. Escolha a que deixa seu código mais claro para a sua situação específica.
Entender else com loops while te dá mais uma ferramenta para escrever código claro e expressivo, especialmente em cenários de busca e validação onde você precisa distinguir entre "encontrou" e "não encontrou" ou "sucesso" e "falha depois de todas as tentativas".
Neste capítulo, exploramos loops while em profundidade, aprendendo como:
- Estruturar loops que repetem código com base em condições
- Evitar loops infinitos atualizando corretamente as variáveis do loop
- Usar
breakpara sair de loops mais cedo quando necessário - Usar
continuepara pular iterações com base em condições - Usar
elsepara lidar com casos em que loops terminam normalmente sembreak
Essas ferramentas te dão um controle poderoso sobre repetição nos seus programas. No próximo capítulo, vamos aprender sobre loops for, que fornecem uma forma mais conveniente de iterar sobre sequências como strings, listas e ranges.