Fluxo de controle

Todo programa que você escreveu até agora funciona do mesmo jeito cada vez: de cima para baixo, uma linha por vez. Isso funciona para scripts simples, mas programas reais precisam tomar decisões e repetir trabalho. Um quiz precisa verificar se a resposta está correta. Um jogo precisa continuar rodando até que o jogador vença ou perca. Este capítulo aborda como fazer seu programa se ramificar e repetir.
Comparações
Antes de você poder tomar uma decisão, você precisa comparar coisas. Operadores de comparação retornam True ou False. O mais importante para acertar cedo: = atribui um valor, == verifica se dois valores são iguais. Misturá-los é um dos erros mais comuns de iniciantes.
5 > 3 # True
5 < 3 # False
5 == 5 # True (note: duplo igual; = é atribuição, == é comparação)
5 != 3 # True ("não igual a")
5 >= 5 # True ("maior que ou igual a")
5 <= 4 # False ("menor que ou igual a")A distinção = vs == confunde quase todos no início. Atribuição (=) armazena um valor; comparação (==) verifica se dois valores são iguais.
Você pode comparar strings também. Python as compara alfabeticamente, caractere por caractere, o que o capítulo Strings cobre em mais detalhes:
"apple" == "apple" # True
"apple" < "banana" # True (a vem antes de b)
"apple" == "Apple" # False (sensível a maiúsculas)= armazena um valor, == verifica se dois valores são iguais. Eu ainda abrandei a marcha e verifiquei novamente quando estou cansado, então você está em boa companhia se isso o confundir. Comparações devolvem True ou False, e funcionam em strings também, alfabeticamente. Combinando condições
and, or e not combinam comparações. and requer que ambos os lados sejam verdadeiros. or requer que pelo menos um lado seja verdadeiro. not inverte o resultado. Esses permitem expressar condições do mundo real como "score está passando AND 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 requer ambos os lados. or requer pelo menos um lado. not inverte.
and quer ambos os lados verdadeiros, or quer pelo menos um, not inverte a resposta. Isso cobre a maioria das condições reais que você escreverá, como "score está passando and o usuário está ativo". Python para de verificar no momento em que sabe o resultado. 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. Tudo mais se comporta como True. Isso significa if results: verifica se uma lista não está vazia sem escrever if len(results) > 0:.
# Todos esses se comportam como False em uma condição:
False, 0, 0.0, "", [], {}, (), None
# Tudo mais se comporta como TrueIsso significa 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.
False em uma condição: 0, "", [] e None. Tudo mais conta como True. É por isso que if results: lê tão limpo como "se há algo na lista", sem len() necessário. if / elif / else
A declaração if executa um bloco de código apenas quando sua condição é True. elif adiciona mais condições a verificar se a primeira era falsa. else captura tudo que não correspondeu a nenhuma condição. Python usa indentação, não chaves, para definir o que pertence a cada bloco.
score = 87
if score >= 90:
print("Grau A")
elif score >= 80:
print("Grau B")
elif score >= 70:
print("Grau C")
else:
print("Abaixo de C")As regras:
ifé obrigatório e sempre vem primeiroelif(abreviação de "else if") é opcional e você pode ter quantos precisarelseé opcional, trata tudo que não correspondeu, e vem por último- 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 ou cosmética. Python a usa para definir estrutura. Indentação inconsistente é um erro de sintaxe.
if executa seu bloco quando a condição é verdadeira, elif verifica mais casos, else captura o resto. Apenas a primeira correspondência é executada. A coisa que me pegou no início: indentação é o que diz ao Python onde cada bloco começa e termina, então mantenha-a consistente. Condições de uma linha
Para atribuições simples de sim/não, Python tem uma forma compacta de uma linha chamada expressão ternária: value_if_true if condition else value_if_false. Use-a apenas quando a lógica é pequena e lê como uma sentença.
label = "passou" if score >= 50 else "reprovou"Esta é uma expressão ternária; ela lê como uma sentença. Use-a quando a lógica é pequena. Para qualquer coisa envolvendo elif, escreva a versão completa.
value_if_true if condition else value_if_false escolhe um de dois valores em uma única linha. É maravilhoso para escolhas bonitinhas como "passou" if score >= 50 else "reprovou". No momento em que a lógica cresce além disso, volte a um bloco `if` normal, lerá melhor. Loops while
Um loop while repete seu bloco enquanto sua condição é True. Use-o quando você não sabe antecipadamente quantas vezes o loop deve ser executado, por exemplo, esperando entrada válida ou tentando novamente até que um trabalho tenha sucesso.
lives = 3
while lives > 0:
print(f"Vidas restantes: {lives}")
lives -= 1
print("Fim de jogo")while é melhor quando você não sabe antecipadamente quantas vezes o loop será executado. Quando você sabe, ou quando você está iterando sobre uma coleção, for é mais limpo.
while continua executando seu bloco enquanto a condição permanece verdadeira. Use quando você não sabe quantas rodadas você precisa, como esperando entrada válida. Certifique-se de que algo dentro do loop se move para a saída, ou ele será executado para sempre, um erro que cometi mais de uma vez. break e continue
break sai do loop imediatamente, não importa quantas iterações restam. continue pula o resto da iteração atual e volta à verificação de condição. Ambos afetam apenas o loop mais interno em que estão.
break sai do loop imediatamente:
target = 5
num = 0
while True:
num += 1
if num == target:
print(f"Encontrado {target}")
break # para o loopwhile 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 loop.
continue pula o resto da iteração atual e volta à verificação de condição:
num = 0
while num < 10:
num += 1
if num % 2 == 0:
continue # pula números pares
print(num) # apenas números ímpares imprimem: 1, 3, 5, 7, 9break salta fora do loop agora, continue pula o resto desta rodada e volta à verificação de condição. Ambos apenas tocam no loop em que estão diretamente dentro. `while True:` com um `break` lê estranho no início, mas é uma forma normal de fazer loop até que algo aconteça. Loops for
Um loop for passa por uma sequência um item de cada 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 ou verifica o comprimento você mesmo.
players = ["Maria", "João", "Paulo"]
for player in players:
print(f"Olá, {player}!")Loops for também funcionam em strings (iterando caractere por caractere) e em qualquer outro tipo de sequência.
for item in sequence caminha por cada item por sua vez, e você nunca toca em um contador ou comprimento você mesmo. Funciona em listas, strings, ranges, muitas coisas. Vindo de outras linguagens, não gerenciar o índice me pareceu estranho no início, depois pareceu um presente. range()
range() gera uma sequência de números para você fazer loop. range(5) dá 0, 1, 2, 3, 4. Você pode controlar início, fim e tamanho de passo. Use quando você precisa que um loop 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 (contando para trás) |
range() não cria uma lista. Ela produz números um de cada vez, que é eficiente mesmo para ranges muito grandes.
range(5) dá `0, 1, 2, 3, 4`, e você pode definir um início, parada e passo. Use quando você quer um loop execute um número definido de vezes. Não constrói uma lista, dá um número por rodada. enumerate()
enumerate() dá tanto o índice quanto o valor enquanto você faz loop, então você não precisa rastrear um contador separadamente. A parte i, player automaticamente recebe um par de valores em cada iteração.
players = ["Maria", "João", "Paulo"]
for i, player in enumerate(players):
print(f"{i + 1}. {player}")
# 1. Maria
# 2. João
# 3. PauloA sintaxe i, player é chamada unpacking. Python divide o par (index, value) em dois nomes automaticamente.
Por padrão enumerate() começa em 0. Passe um valor de início para mudar:
for i, player in enumerate(players, start=1):
print(f"{i}. {player}") # começa em 1enumerate() dá a posição e o valor juntos, então sem contador separado para manter em sincronia. A parte `i, player` pega ambos de uma vez. Passe `start=1` quando você está numerando uma lista para alguém ler. Loops aninhados
Você pode colocar um loop dentro de outro loop. O loop interno executa completamente para cada iteração única do loop 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 loop aninhado afetam apenas o loop mais interno.
Loop-else
Os loops Python podem ter uma cláusula else que é executada apenas se o loop terminou sem atingir um break. Não é comumente usado, mas é a forma mais limpa de escrever "buscar uma lista, e se nada foi encontrado, fazer isto".
target = "Carlos"
names = ["Maria", "João", "Paulo"]
for name in names:
if name == target:
print(f"Encontrado {target}")
break
else:
print(f"{target} não está na lista") # executa porque break nunca disparouSe break é executado, else é ignorado. Se o loop esgota a sequência, else é executado. É um padrão de nicho mas mais limpo que uma variável de bandeira.
Ordenação
sorted() retorna uma nova lista ordenada e deixa a original inalterada. .sort() ordena a lista no lugar e retorna None. O argumento key= permite ordenar por algo que não seja o valor bruto. Por exemplo, ordenar nomes sem distinção de maiúsculas e minúsculas ou ordenar tuplas de jogadores pela 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]Ambas aceitam um argumento key=: uma função aplicada a cada item antes da comparação:
names = ["Carlos", "Maria", "João"]
sorted(names, key=str.lower) # ordenação sem distinção de maiúsculas
players = [("Maria", 87), ("João", 96), ("Paulo", 55)]
sorted(players, key=lambda p: p[1]) # ordenar por pontuaçãolambda p: p[1] é uma função de uma linha: leva uma tupla de jogador e retorna a pontuação. Lambdas recebem tratamento completo no capítulo Lambdas e compreensões.
Para casos simples, use sorted(). Para listas onde você quer modificar no lugar, use .sort().
sorted() devolve uma nova lista ordenada e deixa o original sozinho, .sort() rearanja a lista em si e retorna None. Passe `key=` para ordenar por algo que não seja o valor bruto, como nomes sem distinção de maiúsculas. Em dúvida, use sorted(), é o seguro. Na prática
Faça loop através de pontuações, acumule um total, conte graus de aprovação 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"Média: {average:.1f}")
print(f"Aprovado: {passing}/{len(raw_scores)}")
print(f"Maior pontuação: {sorted(raw_scores, reverse=True)[0]}")
