Pular para o conteúdo principal

Aula 09: Introdução a Listas


Objetivos de Aprendizagem

Ao final desta aula, você será capaz de:

  1. Criar listas em Python e acessar seus elementos por índice
  2. Aplicar fatiamento (slicing) para obter sublistas
  3. Utilizar os principais métodos de lista: append, insert, remove, pop, sort e reverse
  4. Iterar sobre listas usando for e while
  5. Reconhecer quando usar uma lista em vez de variáveis avulsas

Conteúdo Teórico

1. O que é uma Lista?

Até agora, cada variável armazenava um único valor: um número, um texto ou um booleano. Mas e quando precisamos guardar vários valores relacionados? Por exemplo: as notas de um aluno em seis provas, os dias da semana ou os produtos de um carrinho de compras.

Uma lista é uma estrutura de dados que armazena uma sequência ordenada de elementos em uma única variável. Em Python, listas são delimitadas por colchetes [] e os itens são separados por vírgulas.

# Uma variável para cada nota — problemático
nota1 = 7.5
nota2 = 8.0
nota3 = 6.5

# Uma lista com todas as notas — muito melhor
notas = [7.5, 8.0, 6.5, 9.0, 5.5, 7.0]
Conceito Fundamental

Uma lista em Python é uma coleção ordenada, mutável e que aceita elementos de tipos diferentes. "Ordenada" significa que a posição de cada elemento importa e é preservada. "Mutável" significa que podemos alterar o conteúdo após a criação.

Listas podem conter qualquer tipo de dado — inclusive misturado:

# Lista de strings
dias = ["segunda", "terça", "quarta", "quinta", "sexta"]

# Lista de inteiros
primos = [2, 3, 5, 7, 11, 13]

# Lista mista (válido em Python, use com cautela)
misto = [42, "Python", True, 3.14]

# Lista vazia
vazia = []

2. Acessando Elementos por Índice

Cada elemento de uma lista possui um índice (posição). Em Python, os índices começam em zero — o primeiro elemento está na posição 0, o segundo na posição 1, e assim por diante.

frutas = ["maçã", "banana", "laranja", "uva", "manga"]
#índices: 0 1 2 3 4

Para acessar um elemento, usamos o nome da lista seguido do índice entre colchetes:

frutas = ["maçã", "banana", "laranja", "uva", "manga"]

print(frutas[0]) # maçã
print(frutas[2]) # laranja
print(frutas[4]) # manga

Python também suporta índices negativos: -1 acessa o último elemento, -2 o penúltimo, e assim por diante:

print(frutas[-1]) # manga
print(frutas[-2]) # uva
Dica prática

Índices negativos são muito úteis quando você precisa acessar os últimos elementos de uma lista sem saber o tamanho dela.

Tamanho da lista com len()

A função len() retorna o número de elementos de uma lista:

frutas = ["maçã", "banana", "laranja", "uva", "manga"]
print(len(frutas)) # 5

O último índice válido é sempre len(lista) - 1:

ultimo = frutas[len(frutas) - 1] # "manga" — equivalente a frutas[-1]

3. Fatiamento (Slicing)

O fatiamento permite extrair uma parte de uma lista, criando uma nova lista com um subconjunto dos elementos.

A sintaxe é: lista[inicio:fim] — retorna os elementos do índice inicio até fim - 1 (o fim é exclusivo).

numeros = [10, 20, 30, 40, 50, 60, 70]

print(numeros[1:4]) # [20, 30, 40] — índices 1, 2 e 3
print(numeros[0:3]) # [10, 20, 30] — três primeiros
print(numeros[4:]) # [50, 60, 70] — do índice 4 até o fim
print(numeros[:3]) # [10, 20, 30] — do início até o índice 2
print(numeros[:]) # cópia completa da lista

Também é possível usar um passo (step): lista[inicio:fim:passo]

print(numeros[::2]) # [10, 30, 50, 70] — de dois em dois
print(numeros[::-1]) # [70, 60, 50, 40, 30, 20, 10] — invertida

4. Modificando Listas

Listas são mutáveis — podemos alterar seus elementos diretamente:

frutas = ["maçã", "banana", "laranja"]

frutas[1] = "morango" # substitui "banana" por "morango"
print(frutas) # ["maçã", "morango", "laranja"]

Métodos de lista

Métodos são funções associadas a um objeto. Para listas, os principais são:

MétodoO que fazExemplo
append(x)Adiciona x ao finallista.append(10)
insert(i, x)Insere x na posição ilista.insert(0, "início")
remove(x)Remove a primeira ocorrência de xlista.remove("banana")
pop(i)Remove e retorna o elemento na posição i (padrão: último)lista.pop()
sort()Ordena a lista no lugar (crescente por padrão)lista.sort()
reverse()Inverte a lista no lugarlista.reverse()
index(x)Retorna o índice da primeira ocorrência de xlista.index("banana")
count(x)Conta quantas vezes x aparecelista.count(5)
clear()Remove todos os elementoslista.clear()
notas = [7.5, 8.0, 6.5]

notas.append(9.0) # [7.5, 8.0, 6.5, 9.0]
notas.insert(0, 5.0) # [5.0, 7.5, 8.0, 6.5, 9.0]
notas.remove(5.0) # [7.5, 8.0, 6.5, 9.0]
ultimo = notas.pop() # remove 9.0; notas = [7.5, 8.0, 6.5]

notas.sort() # [6.5, 7.5, 8.0]
notas.sort(reverse=True) # [8.0, 7.5, 6.5]
notas.reverse() # [6.5, 7.5, 8.0]

5. Iterando sobre Listas

A forma mais direta de percorrer todos os elementos de uma lista é o laço for:

frutas = ["maçã", "banana", "laranja"]

for fruta in frutas:
print(fruta)
# maçã
# banana
# laranja

Quando você precisa do índice durante a iteração, use enumerate():

for i, fruta in enumerate(frutas):
print(f"{i}: {fruta}")
# 0: maçã
# 1: banana
# 2: laranja

Também é possível iterar com while usando o índice:

i = 0
while i < len(frutas):
print(frutas[i])
i += 1

Exemplo prático: Cálculo de média

notas = [7.5, 8.0, 6.5, 9.0, 5.5]

soma = 0
for nota in notas:
soma += nota

media = soma / len(notas)
print(f"Média: {media:.1f}") # Média: 7.3
Dica prática

Para somar todos os elementos de uma lista de números, Python oferece a função sum():

media = sum(notas) / len(notas)

6. Operações Úteis com Listas

# Verificar se um elemento está na lista
frutas = ["maçã", "banana", "laranja"]
print("banana" in frutas) # True
print("uva" in frutas) # False

# Concatenar listas com +
lista1 = [1, 2, 3]
lista2 = [4, 5, 6]
lista3 = lista1 + lista2 # [1, 2, 3, 4, 5, 6]

# Repetir uma lista com *
zeros = [0] * 5 # [0, 0, 0, 0, 0]

# Funções úteis para listas numéricas
numeros = [3, 1, 4, 1, 5, 9, 2, 6]
print(min(numeros)) # 1
print(max(numeros)) # 9
print(sum(numeros)) # 31

Demonstração em Aula

Os exemplos abaixo formam uma sequência para apresentação ao vivo. Cada bloco introduz um conceito novo construindo sobre o anterior — execute-os na ordem, preferencialmente no terminal interativo do Python (python3) ou em um arquivo .py.

Demo 1 — Por que precisamos de listas?

Mostre o problema de usar variáveis individuais e a solução imediata com uma lista.

# Sem lista: uma variável por nota — inviável para 30 alunos
nota_aluno1 = 8.5
nota_aluno2 = 6.0
nota_aluno3 = 9.5
# ... e assim até nota_aluno30 — imagine calcular a média disso!

# Com lista: todos os dados em uma única estrutura
notas_turma = [8.5, 6.0, 9.5, 4.0, 7.5, 8.0, 5.5, 9.0, 6.5, 7.0]
print(notas_turma)
print(f"Temos {len(notas_turma)} notas cadastradas")

Demo 2 — Indexação: acessando elementos por posição

filmes = ["Matrix", "Inception", "Interstellar", "Dune", "Arrival"]
#índice: 0 1 2 3 4

# Acesso por índice positivo
print(filmes[0]) # Matrix
print(filmes[2]) # Interstellar

# Índices negativos contam a partir do final
print(filmes[-1]) # Arrival — último
print(filmes[-2]) # Dune — penúltimo

# O que acontece com um índice fora do intervalo?
# print(filmes[10]) # IndexError — descomente para demonstrar o erro
Ponto de discussão

Pergunte à turma: qual é o índice de "Inception"? E qual é o índice negativo equivalente?

Demo 3 — len() e a relação com os índices válidos

filmes = ["Matrix", "Inception", "Interstellar", "Dune", "Arrival"]

tamanho = len(filmes)
print(f"A lista tem {tamanho} elementos")
print(f"Índices válidos: 0 a {tamanho - 1}")

# O último índice válido é sempre len(lista) - 1
ultimo = filmes[tamanho - 1]
print(f"Último filme: {ultimo}") # equivalente a filmes[-1]

Demo 4 — Fatiamento (slicing): extraindo partes da lista

notas = [4.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5]
#índice: 0 1 2 3 4 5 6 7 8 9

# lista[inicio:fim] — fim é EXCLUSIVO
print(notas[0:3]) # [4.0, 5.5, 6.0] — primeiros 3
print(notas[7:]) # [8.5, 9.0, 9.5] — do índice 7 ao final
print(notas[:4]) # [4.0, 5.5, 6.0, 6.5] — do início até índice 3

# Com passo: lista[inicio:fim:passo]
print(notas[::2]) # [4.0, 6.0, 7.0, 8.0, 9.0] — posições pares
print(notas[::-1]) # lista invertida
Observação importante

Fatiamento nunca modifica a lista original — ele sempre cria uma nova lista.

Demo 5 — Listas são mutáveis: modificando elementos

compras = ["arroz", "feijão", "macarrão"]
print("Antes:", compras)

compras[1] = "lentilha" # substitui o elemento no índice 1
print("Depois:", compras)

# Contraste: strings são IMUTÁVEIS
texto = "Python"
# texto[0] = "J" # TypeError! Descomente para demonstrar a diferença.

Demo 6 — Métodos: construindo e editando uma lista dinamicamente

Execute linha a linha, imprimindo a lista após cada operação para visualizar a mudança.

playlist = []

playlist.append("Bohemian Rhapsody")
playlist.append("Hotel California")
playlist.append("Stairway to Heaven")
print("Após appends:", playlist)

playlist.insert(0, "Back in Black") # insere no início
playlist.insert(2, "Smells Like Teen Spirit")
print("Após inserts:", playlist)

playlist.remove("Hotel California") # remove por valor
print("Após remove:", playlist)

removida = playlist.pop() # retira e retorna o último
print(f"Removida: {removida}")
print("Após pop():", playlist)

Demo 7 — Ordenação: sort() vs sorted()

numeros = [42, 7, 19, 3, 88, 15]

# sort() modifica a lista original (in-place)
numeros.sort()
print("Crescente:", numeros) # [3, 7, 15, 19, 42, 88]

numeros.sort(reverse=True)
print("Decrescente:", numeros) # [88, 42, 19, 15, 7, 3]

# sorted() retorna uma NOVA lista; a original não é alterada
original = [42, 7, 19, 3, 88, 15]
nova = sorted(original)
print("Original:", original) # [42, 7, 19, 3, 88, 15] — intacta
print("Nova: ", nova) # [3, 7, 15, 19, 42, 88]

Demo 8 — Iteração: for simples e com enumerate()

linguagens = ["Python", "Java", "C", "JavaScript", "Rust"]

# Iteração simples: obtemos cada elemento diretamente
print("=== Linguagens ===")
for linguagem in linguagens:
print(f" - {linguagem}")

# enumerate(): fornece índice e valor juntos
print("\n=== Com numeração ===")
for i, linguagem in enumerate(linguagens):
print(f" {i + 1}. {linguagem}") # +1 para exibir a partir de 1

Demo 9 — Programa completo: análise de notas da turma

Reúne indexação, len(), sum(), max(), min() e iteração em um único programa coeso.

notas = [8.5, 4.0, 7.0, 9.5, 3.5, 6.0, 8.0, 5.5]

media = sum(notas) / len(notas)
maior = max(notas)
menor = min(notas)

acima_da_media = 0
for nota in notas:
if nota >= media:
acima_da_media += 1

print(f"Turma com {len(notas)} alunos")
print(f"Média : {media:.1f}")
print(f"Maior : {maior}")
print(f"Menor : {menor}")
print(f"Acima da média: {acima_da_media} aluno(s)")

Exercícios / Checkpoints

Checkpoint 1: Criação e acesso

Crie uma lista com os nomes de 5 colegas. Imprima o primeiro, o último e o elemento do meio usando indexação. Em seguida, imprima o tamanho da lista com len().

Checkpoint 2: Fatiamento

Dada a lista numeros = [5, 10, 15, 20, 25, 30, 35, 40], use fatiamento para obter:

  1. Os três primeiros elementos
  2. Os três últimos elementos
  3. Apenas os elementos nas posições pares (0, 2, 4, 6)
  4. A lista inteira invertida

Checkpoint 3: Métodos de lista

Parta de uma lista vazia produtos = [] e, usando métodos de lista, construa passo a passo a lista ["arroz", "feijão", "macarrão", "sal", "óleo"]. Depois: remova "sal", ordene alfabeticamente e imprima o resultado.

Checkpoint 4: Iteração com for

Escreva um programa que receba uma lista de preços [12.50, 8.99, 25.00, 5.75, 17.30] e imprima cada preço com 10% de desconto aplicado, no formato: "Preço original: R$ 12.50 → Com desconto: R$ 11.25".

Checkpoint 5: Análise conceitual

Explique com suas palavras: qual a diferença entre usar lista.sort() e a função sorted(lista)? Em que situação cada uma seria mais adequada? (Dica: experimente no Python e observe o que acontece com a lista original em cada caso.)

Checkpoint 6: Problema aplicado

Dado um cadastro de alunos representado por uma lista de notas: [8.5, 4.0, 7.0, 9.5, 3.5, 6.0, 8.0, 5.5], escreva um programa que calcule e imprima:

  • A média da turma
  • A maior nota
  • A menor nota
  • Quantos alunos estão acima da média

Situações Problema

As duas situações abaixo são para implementação em aula. Elas exigem a combinação de vários conceitos da aula — não há uma única solução certa. Incentive os alunos a experimentar, errar e discutir abordagens diferentes.


Situação Problema 1: Análise de Temperaturas com Detecção de Onda de Calor

Contexto: Uma estação meteorológica registrou as temperaturas diárias (em °C) de uma cidade ao longo de duas semanas. O departamento de saúde quer identificar períodos de risco para a população.

Código inicial:

temperaturas = [28.5, 31.2, 30.8, 33.1, 29.7, 27.3, 26.8,
32.4, 35.1, 34.9, 33.7, 31.5, 29.2, 28.1]

dias = ["Seg", "Ter", "Qua", "Qui", "Sex", "Sáb", "Dom",
"Seg", "Ter", "Qua", "Qui", "Sex", "Sáb", "Dom"]

Tarefas:

  1. Calcule e exiba a temperatura média do período.
  2. Identifique o dia mais quente e o mais frio, exibindo o nome do dia e a temperatura.
  3. Liste todos os dias cuja temperatura ficou acima da média, no formato: "Qui (semana 1): 33.1°C".
  4. Detecte se houve alguma "onda de calor": três ou mais dias consecutivos com temperatura acima de 32°C. Se sim, informe quantos dias consecutivos foram e em qual dia começou.
Dica para a tarefa 4

Você precisará percorrer a lista com um índice e verificar temperaturas[i], temperaturas[i+1] e temperaturas[i+2] ao mesmo tempo. Cuidado com o limite do índice!

Saída esperada (aproximada):

Média do período: 30.9°C
Mais quente: Ter (semana 2) — 35.1°C
Mais frio : Dom (semana 1) — 26.8°C

Dias acima da média:
Qui (semana 1): 33.1°C
Seg (semana 2): 32.4°C
...

Onda de calor detectada! 4 dias consecutivos a partir de Seg (semana 2).
Ver solução
# Tarefa 1: temperatura média
media = sum(temperaturas) / len(temperaturas)
print(f"Média do período: {media:.1f}°C")

# Tarefa 2: dia mais quente e mais frio
indice_max = 0
indice_min = 0
for i in range(len(temperaturas)):
if temperaturas[i] > temperaturas[indice_max]:
indice_max = i
if temperaturas[i] < temperaturas[indice_min]:
indice_min = i

semana_max = "semana 1" if indice_max < 7 else "semana 2"
semana_min = "semana 1" if indice_min < 7 else "semana 2"
print(f"Mais quente: {dias[indice_max]} ({semana_max}) — {temperaturas[indice_max]}°C")
print(f"Mais frio : {dias[indice_min]} ({semana_min}) — {temperaturas[indice_min]}°C")

# Tarefa 3: dias acima da média
print("\nDias acima da média:")
for i in range(len(temperaturas)):
if temperaturas[i] > media:
semana = "semana 1" if i < 7 else "semana 2"
print(f" {dias[i]} ({semana}): {temperaturas[i]}°C")

# Tarefa 4: onda de calor — janela de 3 índices consecutivos
onda_detectada = False
for i in range(len(temperaturas) - 2):
if (temperaturas[i] > 32.0 and
temperaturas[i + 1] > 32.0 and
temperaturas[i + 2] > 32.0):
if i == 0 or temperaturas[i - 1] <= 32.0: # início de nova sequência
duracao = 3
while i + duracao < len(temperaturas) and temperaturas[i + duracao] > 32.0:
duracao += 1
semana = "semana 1" if i < 7 else "semana 2"
print(f"\nOnda de calor detectada! {duracao} dias consecutivos a partir de {dias[i]} ({semana}).")
onda_detectada = True

if not onda_detectada:
print("\nNenhuma onda de calor detectada no período.")

Situação Problema 2: Fila de Atendimento com Prioridade

Contexto: Uma UBS (Unidade Básica de Saúde) precisa gerenciar sua fila de atendimento. Clientes comuns entram no final da fila. Clientes com prioridade (idosos, gestantes, pessoas com deficiência) entram logo após o primeiro da fila — que já está sendo atendido e não pode ser deslocado.

Código inicial:

# Fila no início do dia — cada string é o nome do paciente
fila = ["Carlos", "Maria", "João", "Ana"]

# Operações a simular (execute na ordem):
# 1. "Paulo" chega e entra normalmente no final da fila
# 2. "Dona Rosa" tem prioridade — entra logo após o primeiro
# 3. "Carlos" (primeiro da fila) é chamado para atendimento; imprima: "Chamando: Carlos"
# 4. "Lucas" chega e entra normalmente
# 5. "Seu Antônio" tem prioridade — entra logo após o primeiro da fila atual
# 6. Exiba a fila final com a posição de cada pessoa (1ª, 2ª, 3ª...)
# 7. Informe quantas pessoas ainda aguardam atendimento

Tarefas:

  1. Simule cada operação acima usando os métodos corretos (append, insert, pop).
  2. Após cada operação, imprima o estado atual da fila (para facilitar a depuração).
  3. Exiba a fila final numerada e o total de pessoas aguardando.
  4. Extensão: adapte o programa para simular o atendimento de todos os pacientes na ordem correta, chamando-os um a um até a fila esvaziar.
Dica para a prioridade

Um paciente prioritário entra na posição 1 (índice 1) — não no início absoluto (índice 0), pois o primeiro já está sendo atendido.

Saída esperada (após todas as operações):

[Após Paulo entrar] : ['Carlos', 'Maria', 'João', 'Ana', 'Paulo']
[Após Dona Rosa] : ['Carlos', 'Dona Rosa', 'Maria', 'João', 'Ana', 'Paulo']
Chamando: Carlos
[Após Lucas entrar] : ['Dona Rosa', 'Maria', 'João', 'Ana', 'Paulo', 'Lucas']
[Após Seu Antônio] : ['Dona Rosa', 'Seu Antônio', 'Maria', 'João', 'Ana', 'Paulo', 'Lucas']

Fila atual:
1ª: Dona Rosa
2ª: Seu Antônio
3ª: Maria
...
Total aguardando: 7 pacientes
Ver solução
# 1. Paulo entra normalmente no final
fila.append("Paulo")
print(f"[Após Paulo entrar] : {fila}")

# 2. Dona Rosa tem prioridade — entra logo após o primeiro (índice 1)
fila.insert(1, "Dona Rosa")
print(f"[Após Dona Rosa] : {fila}")

# 3. Carlos (primeiro) é chamado para atendimento
chamado = fila.pop(0)
print(f"Chamando: {chamado}")
print(f"[Após Carlos sair] : {fila}")

# 4. Lucas entra normalmente
fila.append("Lucas")
print(f"[Após Lucas entrar] : {fila}")

# 5. Seu Antônio tem prioridade — entra logo após o primeiro atual
fila.insert(1, "Seu Antônio")
print(f"[Após Seu Antônio] : {fila}")

# 6. Fila final com posições
print("\nFila atual:")
for i, pessoa in enumerate(fila):
print(f" {i + 1}ª: {pessoa}")

# 7. Total aguardando
print(f"\nTotal aguardando: {len(fila)} paciente(s)")

# Extensão: atender todos os pacientes na ordem
print("\n--- Extensão: atendendo todos ---")
while fila:
chamado = fila.pop(0)
print(f"Chamando: {chamado}")
print("Fila vazia — atendimento encerrado.")

Resumo da Aula

Nesta aula, você aprendeu:

  • Uma lista armazena uma sequência ordenada e mutável de elementos em Python
  • Elementos são acessados por índice (iniciando em 0); índices negativos acessam do final
  • Fatiamento (lista[inicio:fim]) extrai sublistas sem modificar a original
  • Os principais métodos: append, insert, remove, pop, sort, reverse
  • O laço for percorre cada elemento; enumerate() fornece índice e elemento juntos

Próxima aula: Dicionários — estrutura chave-valor para dados mais expressivos


Referências

Leitura Essencial

  • Python Software Foundation. Built-in Types — Lists. Documentação oficial do Python. Disponível em: docs.python.org/3/library/stdtypes.html#lists
    • Referência completa de todos os métodos e comportamentos de listas.
  • Forbellone, A. L. V.; Eberspächer, H. F. Lógica de Programação: A Construção de Algoritmos e Estruturas de Dados. 3ª ed. São Paulo: Pearson, 2005.
    • Capítulo sobre vetores e estruturas sequenciais fundamenta a compreensão das listas.

Aprofundamento (Opcional)

  • Lutz, M. Aprendendo Python. 5ª ed. São Paulo: O'Reilly Brasil, 2013.
    • Capítulo sobre sequências aprofunda operações e idiomas avançados de listas.
  • Python Software Foundation. List Comprehensions. Disponível em: docs.python.org/3/tutorial/datastructures.html#list-comprehensions
    • Forma compacta e pythônica de criar listas. Tema para explorar após dominar o básico.