Controle de fluxo
Todo programa que você escreveu até agora é executado da mesma forma todas as vezes: de cima para baixo, uma linha por vez. Isso funciona para scripts simples, mas programas reais precisam tomar decisões e repetir tarefas. Um quiz precisa verificar se a resposta está correta. Um jogo precisa continuar rodando até o jogador vencer ou perder. Este capítulo aborda como fazer seu programa ramificar e repetir.
Comparações
Antes de poder tomar uma decisão, você precisa comparar coisas. Operadores de comparação retornam True ou False. O mais importante de acertar logo cedo: = atribui um valor, == verifica se dois valores são iguais. Confundir os dois é um dos erros mais comuns para iniciantes.
5 > 3 # True
5 < 3 # False
5 == 5 # True (observação: igual duplo; = é atribuição, == é comparação)
5 != 3 # True ("diferente de")
5 >= 5 # True ("maior ou igual a")
5 <= 4 # False ("menor ou igual a")A distinção entre = e == confunde quase todo mundo no início. A atribuição (=) armazena um valor; a comparação (==) verifica se dois valores são iguais.
Você também pode comparar strings. O Python as compara alfabeticamente:
"apple" == "apple" # True
"apple" < "banana" # True (a vem antes de b)
"apple" == "Apple" # False (sensível a maiúsculas/minúsculas)Combinando condições
and, or e not combinam comparações. and exige que ambos os lados sejam verdadeiros. or exige pelo menos um dos lados. not inverte o resultado. Eles permitem expressar condições do mundo real como "nota está aprovada E usuário está ativo".
age = 25
score = 88
age >= 18 and score >= 80 # True (ambos devem ser verdadeiros)
age < 18 or score >= 80 # True (pelo menos um deve ser verdadeiro)
not age >= 18 # False (inverte o resultado)and exige ambos os lados. or exige pelo menos um lado. not inverte.
Truthy e falsy
Todo valor em Python tem uma interpretação booleana, mesmo que não seja True ou False. Strings vazias, zero, listas vazias e None se comportam como False em uma condição. Todo o resto se comporta como True. Isso significa que if results: verifica se uma lista não está vazia sem precisar escrever if len(results) > 0:.
# Todos estes se comportam como False em uma condição:
False, 0, 0.0, "", [], {}, (), None
# Todo o resto se comporta como TrueIsso significa que if results: é uma forma natural de dizer "se a lista não está vazia", e if name: verifica se uma string tem algum conteúdo.
if / elif / else
A instrução if executa um bloco de código apenas quando sua condição é True. elif adiciona mais condições para verificar caso a primeira tenha sido falsa. else captura tudo que não correspondeu a nenhuma condição. O Python usa indentação, não chaves, para definir o que pertence a cada bloco.
score = 87
if score >= 90:
print("A grade")
elif score >= 80:
print("B grade")
elif score >= 70:
print("C grade")
else:
print("Below C")As regras:
ifé obrigatório e sempre vem primeiroelif(abreviação de "else if") é opcional e você pode ter quantos precisarelseé opcional, lida com tudo que não correspondeu e vem por último- O Python usa indentação (4 espaços) para marcar o que pertence a cada bloco; não há chaves
A indentação não é opcional nem cosmética. O Python a usa para definir estrutura. Indentação inconsistente é um erro de sintaxe.
Condições em uma linha
Para atribuições simples de sim/não, o Python tem uma forma compacta em uma linha chamada expressão ternária: valor_se_verdadeiro if condição else valor_se_falso. Use-a apenas quando a lógica é genuinamente simples e se lê como uma frase.
label = "pass" if score >= 50 else "fail"Esta é uma expressão ternária; lê-se como uma frase. Use-a quando a lógica é genuinamente simples. Para qualquer coisa envolvendo elif, escreva a versão completa.
Laços while
Um laço while repete seu bloco enquanto sua condição é True. Use-o quando você não sabe de antemão quantas vezes o laço deve rodar, por exemplo, esperando por entrada válida ou tentando novamente até um trabalho ter sucesso.
lives = 3
while lives > 0:
print(f"Lives remaining: {lives}")
lives -= 1
print("Game over")while é melhor quando você não sabe de antemão quantas vezes o laço será executado. Quando você sabe, ou quando está iterando sobre uma coleção, for é mais limpo.
break e continue
break sai do laço imediatamente, não importa quantas iterações restem. continue pula o restante da iteração atual e volta para a verificação da condição. Ambos afetam apenas o laço mais interno em que estão.
break sai do laço imediatamente:
target = 5
num = 0
while True:
num += 1
if num == target:
print(f"Found {target}")
break # para o laçowhile True: com um break é um padrão válido e comum quando a condição de saída é complexa ou precisa acontecer no final do corpo do laço.
continue pula o restante da iteração atual e volta para a verificação da condição:
num = 0
while num < 10:
num += 1
if num % 2 == 0:
continue # pula números pares
print(num) # apenas números ímpares são impressos: 1, 3, 5, 7, 9Laços for
Um laço for percorre uma sequência um item por vez: uma lista, uma string, um intervalo de números. A variável que você nomeia após for recebe cada item por sua vez. Você não gerencia um contador nem verifica o comprimento.
players = ["Ana", "Bruno", "Carlos"]
for player in players:
print(f"Hello, {player}!")Laços for também funcionam em strings (iterando caractere por caractere) e em qualquer outro tipo de sequência.
range()
range() gera uma sequência de números para você iterar. range(5) fornece 0, 1, 2, 3, 4. Você pode controlar o início, o fim e o tamanho do passo. Use-o quando precisar que um laço execute um número específico de vezes.
for i in range(5):
print(i) # 0, 1, 2, 3, 4range() tem três formas:
| Chamada | O que produz |
|---|---|
range(5) | 0, 1, 2, 3, 4 |
range(2, 6) | 2, 3, 4, 5 |
range(0, 10, 2) | 0, 2, 4, 6, 8 (passo de 2) |
range(5, 0, -1) | 5, 4, 3, 2, 1 (contagem regressiva) |
range() não cria uma lista. Ele produz números um de cada vez, o que é eficiente mesmo para intervalos muito grandes.
enumerate()
enumerate() fornece tanto o índice quanto o valor enquanto você itera, então você não precisa rastrear um contador separadamente. A parte i, player recebe automaticamente um par de valores em cada iteração.
players = ["Ana", "Bruno", "Carlos"]
for i, player in enumerate(players):
print(f"{i + 1}. {player}")
# 1. Ana
# 2. Bruno
# 3. CarlosA sintaxe i, player é chamada de desempacotamento. O Python divide o par (index, value) em dois nomes automaticamente.
Por padrão, enumerate() começa em 0. Passe um valor inicial para alterar isso:
for i, player in enumerate(players, start=1):
print(f"{i}. {player}") # começa em 1Laços aninhados
Você pode colocar um laço dentro de outro laço. O laço interno é executado completamente para cada iteração do laço externo. É assim que você processa grades, combinações ou qualquer dado com dois níveis de estrutura.
rows = [1, 2, 3]
cols = ["A", "B"]
for row in rows:
for col in cols:
print(f"{col}{row}", end=" ")
print() # nova linha após cada linha
# A1 B1
# A2 B2
# A3 B3break e continue dentro de um laço aninhado afetam apenas o laço mais interno.
Loop-else
Laços Python podem ter uma cláusula else que é executada apenas se o laço terminar sem encontrar um break. Não é comumente usada, mas é a forma mais limpa de escrever "pesquise uma lista e, se nada for encontrado, faça isso".
target = "Daniel"
names = ["Ana", "Bruno", "Carlos"]
for name in names:
if name == target:
print(f"Found {target}")
break
else:
print(f"{target} not in list") # executa porque break nunca foi disparadoSe break executar, o else é ignorado. Se o laço esgotar a sequência, else é executado. É um padrão de nicho, mas mais limpo do que uma variável de flag.
Ordenação
sorted() retorna uma nova lista ordenada e deixa o original inalterado. .sort() ordena a lista no local e retorna None. O argumento key= permite ordenar por algo diferente do valor bruto. Por exemplo, ordenar nomes sem distinção entre maiúsculas e minúsculas ou ordenar tuplas de jogadores por sua pontuação.
scores = [87, 42, 96, 55, 71]
ranked = sorted(scores) # [42, 55, 71, 87, 96] (nova lista)
scores.sort() # ordena a lista original, retorna None
scores.sort(reverse=True) # [96, 87, 71, 55, 42]Ambos aceitam um argumento key=: uma função aplicada a cada item antes da comparação:
names = ["Carlos", "Ana", "Bruno"]
sorted(names, key=str.lower) # ordenação sem distinção entre maiúsculas/minúsculas
players = [("Ana", 87), ("Bruno", 96), ("Carlos", 55)]
sorted(players, key=lambda p: p[1]) # ordena por pontuaçãoO que é um lambda?
lambda p: p[1] é uma função de uma linha. Recebe uma tupla de jogador e retorna a pontuação. Funções lambda são abordadas no capítulo Lambda, comprehensions e zip.
Para casos simples, use sorted(). Para listas em que você quer modificar no local, use .sort().
Na prática
Itere pelas pontuações, acumule um total, conte as notas aprovadas e imprima um resumo:
raw_scores = [87, 42, 96, 55, 71, 63]
total = 0
passing = 0
for score in raw_scores:
total += score
if score >= 60:
passing += 1
average = total / len(raw_scores)
print(f"Average: {average:.1f}")
print(f"Passing: {passing}/{len(raw_scores)}")
print(f"Top score: {sorted(raw_scores, reverse=True)[0]}")
