10. Padrões de lista¶
Nesta aula
Ideia central: quase tudo que você vai precisar fazer com uma lista este semestre cabe em cinco formas. Elas não são truque de decoração — são o vocabulário que a disciplina seguinte já vai supor que você conhece.
Ao fim você vai conseguir: somar todos os valores de uma lista; contar quantos atendem a uma condição; achar o maior ou o menor sem o candidato inicial que mente; separar para uma lista nova o que interessa; e construir, a partir de uma lista, uma lista nova de totais que crescem.
Cinco formas, uma lista só¶
Os três primeiros padrões já apareceram na Unidade 3 — acumulador, contador, extremo — só que ali eles processavam números que chegavam pelo teclado, um de cada vez. Agora a lista já existe inteira antes do laço começar, e dois padrões novos entram: os que não terminam num número, mas numa lista nova.
| Padrão | O que faz | Nasce como |
|---|---|---|
| somar tudo | acumulador sobre a lista inteira | total = 0 |
| contar sob condição | contador com um if dentro do for |
contagem = 0 |
| achar o maior/menor | extremo, com candidato honesto | = lista[0] |
| filtrar para lista nova | guarda só quem passa no if |
= [] |
| acumular em lista nova | guarda um total que cresce a cada volta | = [] e total = 0 |
A maior parte dos exemplos abaixo percorre o mesmo cenário — o consumo de
dados de um cliente ao longo do mês. Dois trocam de domínio de propósito: o
padrão 3 precisa de uma lista com valores negativos para expor o defeito, e o
padrão 5 usa gastos em vez de consumo. Repare que a estrutura muda pouco de um
padrão para o outro — é sempre um for, às vezes com um if dentro.
Padrão 1 · somar tudo¶
# Padrao 1: somar tudo -- acumulador percorrendo uma lista ja pronta.
consumo_gb = [4.2, 1.8, 5.0, 0.9, 3.3]
total = 0
for consumo in consumo_gb:
total = total + consumo
print(f"Consumo total do mes: {total:.1f} GB")
O mesmo acumulador do capítulo 7: total nasce em 0, antes do for, e
cresce em toda volta. A única diferença é que agora ele soma os itens de uma
lista pronta em vez de somar o que acabou de vir do input().
Padrão 2 · contar sob condição¶
# Padrao 2: contar sob condicao -- contador com um if dentro do for.
consumo_gb = [4.2, 1.8, 5.0, 0.9, 3.3]
meta = 3.0
dias_acima = 0
for consumo in consumo_gb:
if consumo > meta:
dias_acima = dias_acima + 1
print("Dias acima da meta:", dias_acima)
dias_acima nasce em 0 e só cresce dentro do if. Repare na diferença
de uma linha para o padrão anterior: total = total + consumo soma o valor;
dias_acima = dias_acima + 1 soma sempre 1, e só quando a condição é
verdadeira.
Padrão 3 · achar o maior ou o menor¶
Este é o padrão em que a maioria das pessoas escreve algo que parece certo
e está errado. O hábito mais comum é começar o candidato em 0:
Funciona quando todos os valores são positivos — e é exatamente por isso que o defeito sobrevive sem ninguém notar. Ele aparece na primeira lista que tem só valores negativos:
# Padrao 3: o extremo -- o candidato inicial tem de ser HONESTO.
saldos = [-120.0, -35.0, -280.0, -60.0]
maior_errado = 0
for saldo in saldos:
if saldo > maior_errado:
maior_errado = saldo
maior_certo = saldos[0]
for saldo in saldos:
if saldo > maior_certo:
maior_certo = saldo
print("Maior saldo (comecando em 0):", maior_errado)
print("Maior saldo (comecando no primeiro):", maior_certo)
Os quatro saldos são todos negativos, o maior de verdade é -35.0 — e o laço
que começa em 0 responde 0, um saldo que não existe na lista. O programa
não travou, não avisou nada: só mentiu, com uma cara plausível de resposta
certa.
Por que 0 não é um candidato honesto
0 não é "nenhum valor ainda" — é um valor real, e ele entra na
disputa como se tivesse sido medido. Se a lista inteira for negativa, 0
vence sempre, porque é maior que qualquer um deles. Se você estivesse
procurando o menor valor e começasse em 0, o defeito seria ainda
mais traiçoeiro: numa lista de consumos, que nunca são negativos, menor =
0 venceria sempre — não é um erro que aparece de vez em quando, é um
erro que acontece em toda execução, com qualquer entrada, e o
resultado (0.0) sempre parece uma resposta plausível.
A correção é uma troca de uma linha: o candidato inicial é o primeiro item da própria lista, não um número inventado.
Agora o candidato inicial é um saldo que existe de verdade — o pior caso possível é o laço nunca achar nada melhor, e a resposta continuar sendo o próprio primeiro item. Nunca um valor de fora da lista.
💡 Pense assim: o primeiro concorrente já está classificado
Um campeonato não compara os atletas com "zero pontos" antes de começar: o primeiro que aparece já é o líder provisório, e só perde o posto para quem jogar melhor de verdade. Comparar com zero é inventar um concorrente que não existe — e que pode estar roubando o título de quem competiu.
Padrão 4 · filtrar para uma lista nova¶
Às vezes você não quer um número — quer separar os itens que interessam, mantendo o valor original de cada um.
# Padrao 4: filtrar para uma lista NOVA -- a lista original nao muda.
consumo_gb = [4.2, 1.8, 5.0, 0.9, 3.3]
meta = 3.0
acima_da_meta = []
for consumo in consumo_gb:
if consumo > meta:
acima_da_meta.append(consumo)
print("Consumos acima da meta:", acima_da_meta)
print("Quantos:", len(acima_da_meta))
acima_da_meta nasce [], e só recebe um item quando o if dá certo. É o
padrão 2 (contador) com uma troca: em vez de somar 1, você append o valor
inteiro. A lista original, consumo_gb, não muda em nada.
Padrão 5 · acumular numa lista nova¶
O último padrão junta um acumulador com uma lista nova: a cada volta, o total cresce e o valor dele naquele momento é guardado.
# Padrao 5: acumular numa lista NOVA -- um total que cresce, guardado a cada volta.
gastos = [50.0, 30.0, 20.0, 45.0, 15.0]
acumulado = []
total = 0
for gasto in gastos:
total = total + gasto
acumulado.append(total)
print("Saldo gasto acumulado:", acumulado)
acumulado guarda, em ordem, "quanto já tinha sido gasto até aqui" depois de
cada dia — um saldo que cresce dia a dia, não só o total final. É a diferença
entre "quanto gastei no mês" (um número, padrão 1) e "quanto eu já tinha
gastado em cada dia do mês" (uma lista nova, padrão 5).
Os cinco lado a lado¶
| Padrão | Nasce | Cresce quando | Termina em |
|---|---|---|---|
| somar tudo | total = 0 |
toda volta | um número |
| contar sob condição | contagem = 0 |
só quando o if é verdadeiro |
um número |
| achar o maior/menor | = lista[0] |
só quando acha um melhor | um número |
| filtrar para lista nova | = [] |
só quando o if é verdadeiro |
uma lista |
| acumular em lista nova | = [] e total = 0 |
toda volta | uma lista |
A pergunta que decide qual usar é sempre a mesma da Unidade 3, com uma adição: o que eu preciso no fim — um número ou uma lista?
Erros comuns deste capítulo¶
| Mensagem ou sintoma | Causa provável |
|---|---|
| o maior/menor deu um valor que não está na lista | o candidato começou em 0 (ou outro número inventado) em vez de lista[0] |
| a lista filtrada veio vazia quando não devia | o if está com a condição trocada, ou comparando com a variável errada |
| a lista nova ficou do mesmo tamanho da original, mas devia ser menor | trocou filtrar (padrão 4, if antes do append) por acumular (padrão 5, append sempre) |
| o total dentro da lista acumulada está errado | o append veio antes de somar o valor da volta |
contagem e total deram o mesmo número |
um dos dois está somando o valor em vez de somar 1 (ou o contrário) |
Resumo¶
- Somar tudo: acumulador de sempre, agora sobre uma lista pronta.
- Contar sob condição: contador que só cresce dentro de um
if. - Achar o maior/menor: o candidato inicial tem de ser um valor que existe
na lista —
lista[0], nunca0. É o erro que não dá erro desta unidade. - Filtrar para lista nova:
appendsó quando oifé verdadeiro; a lista original não muda. - Acumular em lista nova: soma e
appendjuntos, a cada volta — guarda o total como ele estava em cada momento, não só no fim.
Para praticar¶
Com estes cinco padrões você processa qualquer lista de números que este semestre vai te dar. A Unidade 5 troca o número pelo texto — e boa parte destes mesmos padrões volta a aparecer, agora percorrendo letras em vez de itens.