Aula 11: Tuplas e Conjuntos
Objetivos de Aprendizagem
Ao final desta aula, você será capaz de:
- Criar e acessar tuplas, compreendendo sua imutabilidade
- Identificar situações em que tuplas são preferíveis a listas
- Criar conjuntos (
set) e utilizá-los para eliminar duplicatas - Aplicar operações de conjunto: união, interseção e diferença
- Comparar listas, tuplas e conjuntos, escolhendo a estrutura adequada
Conteúdo Teórico
1. Tuplas
O que é uma tupla?
Uma tupla é uma sequência ordenada de elementos, assim como a lista — mas com uma diferença fundamental: ela é imutável. Uma vez criada, seus elementos não podem ser alterados, adicionados ou removidos.
# Lista — mutável
frutas_lista = ["maçã", "banana", "laranja"]
frutas_lista[0] = "uva" # OK
# Tupla — imutável
frutas_tupla = ("maçã", "banana", "laranja")
frutas_tupla[0] = "uva" # TypeError: 'tuple' object does not support item assignment
Imutabilidade significa que o objeto não pode ser modificado após sua criação. Isso garante que os dados permanecem íntegros e protegidos contra alterações acidentais.
Criando tuplas
Tuplas são delimitadas por parênteses ():
coordenada = (10.5, -23.4) # par de coordenadas geográficas
rgb = (255, 128, 0) # cor laranja em RGB
vazia = () # tupla vazia
um_elemento = (42,) # tupla com um elemento — a vírgula é obrigatória!
# Sem parênteses também funciona (empacotamento de tupla)
ponto = 3, 7
print(type(ponto)) # <class 'tuple'>
(42) não é uma tupla — é apenas o número 42 entre parênteses. Para criar uma tupla de um único elemento, a vírgula final é obrigatória: (42,).
Acessando elementos
Tuplas usam a mesma indexação e fatiamento das listas:
cores = ("vermelho", "verde", "azul")
print(cores[0]) # vermelho
print(cores[-1]) # azul
print(cores[1:]) # ('verde', 'azul')
print(len(cores)) # 3
Desempacotamento de tupla
Uma das características mais úteis das tuplas é o desempacotamento: atribuir os elementos da tupla a variáveis separadas em uma única linha.
ponto = (3, 7)
x, y = ponto
print(f"x={x}, y={y}") # x=3, y=7
# Útil ao iterar com enumerate ou .items()
aluno = {"nome": "João", "nota": 9.5}
for chave, valor in aluno.items():
print(f"{chave} → {valor}")
Quando usar tupla em vez de lista?
Use tupla quando:
- Os dados são fixos por natureza — coordenadas GPS, data de nascimento, configurações constantes
- Você quer proteger os dados contra modificação acidental
- Os dados serão usados como chave de dicionário (listas não podem ser chaves; tuplas podem)
- A semântica indica um registro com posições fixas:
(latitude, longitude),(dia, mês, ano)
Use lista quando você precisa adicionar, remover ou modificar elementos após a criação.
| Característica | Lista | Tupla |
|---|---|---|
| Mutabilidade | Mutável | Imutável |
| Sintaxe | [a, b, c] | (a, b, c) |
| Pode ser chave de dict | Não | Sim |
| Uso típico | Coleções que mudam | Registros fixos |
2. Conjuntos (Sets)
O que é um conjunto?
Um conjunto (set) é uma coleção não ordenada de elementos únicos (sem duplicatas). Ele é inspirado no conceito matemático de conjunto.
# Criando um conjunto
linguagens = {"Python", "Java", "C++", "Python", "Java"}
print(linguagens)
# {'Python', 'Java', 'C++'} — duplicatas removidas automaticamente
Dois princípios definem os conjuntos:
- Unicidade: cada elemento aparece no máximo uma vez
- Sem ordem garantida: a posição dos elementos não é preservada — não há índice
Criando conjuntos
numeros = {1, 2, 3, 4, 5}
vazio = set() # conjunto vazio — NÃO use {}, pois {} cria dicionário vazio!
# A partir de uma lista (remove duplicatas)
notas_brutas = [8.0, 7.5, 8.0, 9.0, 7.5, 6.0]
notas_unicas = set(notas_brutas)
print(notas_unicas) # {8.0, 7.5, 9.0, 6.0}
Adicionando e removendo elementos
frutas = {"maçã", "banana"}
frutas.add("laranja") # adiciona um elemento
frutas.remove("banana") # remove — KeyError se não existir
frutas.discard("uva") # remove sem erro se não existir
print(len(frutas)) # 2
# Verificar pertencimento — muito eficiente em conjuntos
print("maçã" in frutas) # True
3. Operações de Conjunto
As operações matemáticas de conjuntos estão disponíveis em Python tanto por métodos quanto por operadores:
A = {1, 2, 3, 4, 5}
B = {4, 5, 6, 7, 8}
União — | ou .union()
Todos os elementos de A e de B (sem repetição):
print(A | B) # {1, 2, 3, 4, 5, 6, 7, 8}
print(A.union(B)) # mesmo resultado
Interseção — & ou .intersection()
Apenas os elementos que estão em A e em B:
print(A & B) # {4, 5}
print(A.intersection(B)) # {4, 5}
Diferença — - ou .difference()
Elementos que estão em A mas não estão em B:
print(A - B) # {1, 2, 3}
print(A.difference(B)) # {1, 2, 3}
Diferença simétrica — ^ ou .symmetric_difference()
Elementos que estão em A ou em B, mas não nos dois:
print(A ^ B) # {1, 2, 3, 6, 7, 8}
print(A.symmetric_difference(B)) # {1, 2, 3, 6, 7, 8}
Subconjunto e superconjunto
C = {1, 2}
print(C.issubset(A)) # True — C ⊆ A
print(A.issuperset(C)) # True — A ⊇ C
4. Exemplo Prático: Removendo Duplicatas e Comparando Listas
# Alunos que entregaram TP1 e TP2
entregaram_tp1 = ["Ana", "Bruno", "Carlos", "Diana", "Ana"]
entregaram_tp2 = ["Bruno", "Diana", "Eduardo", "Carlos"]
set_tp1 = set(entregaram_tp1)
set_tp2 = set(entregaram_tp2)
print("Entregaram ambos os TPs:", set_tp1 & set_tp2)
# {'Bruno', 'Carlos', 'Diana'}
print("Entregaram apenas o TP1:", set_tp1 - set_tp2)
# {'Ana'}
print("Entregaram apenas o TP2:", set_tp2 - set_tp1)
# {'Eduardo'}
print("Entregaram pelo menos um:", set_tp1 | set_tp2)
# {'Ana', 'Bruno', 'Carlos', 'Diana', 'Eduardo'}
5. Comparativo Geral das Estruturas
| Característica | Lista | Tupla | Conjunto | Dicionário |
|---|---|---|---|---|
| Ordenada? | Sim | Sim | Não | Sim (Python 3.7+) |
| Mutável? | Sim | Não | Sim | Sim |
| Duplicatas? | Sim | Sim | Não | Chaves únicas |
| Acesso por índice? | Sim | Sim | Não | Por chave |
| Sintaxe | [] | () | {} | {k: v} |
Exercícios / Checkpoints
Checkpoint 1: Tuplas básicas
Crie uma tupla representando uma data (dia, mes, ano). Desempacote-a em três variáveis e imprima no formato "Data: DD/MM/AAAA". Tente modificar um dos elementos e descreva o erro que ocorre.
Checkpoint 2: Tuplas como chaves de dicionário
Crie um dicionário que mapeie coordenadas (latitude, longitude) para nomes de cidades:
cidades = {
(-23.55, -46.63): "São Paulo",
(-22.91, -43.17): "Rio de Janeiro",
(-19.92, -43.94): "Belo Horizonte"
}
Acesse e imprima o nome da cidade de São Paulo usando sua coordenada como chave.
Checkpoint 3: Eliminando duplicatas
Dado o cadastro de inscrições abaixo (com repetições por erro de sistema), use conjuntos para encontrar os inscritos únicos e contar quantos são:
inscricoes = ["Ana", "Bruno", "Carlos", "Ana", "Diana", "Bruno", "Eduardo", "Carlos", "Ana"]
Checkpoint 4: Operações de conjunto
Duas turmas fizeram o mesmo curso em semestres diferentes:
turma_2025_1 = {"Alice", "Bob", "Carol", "David", "Eva"}
turma_2025_2 = {"Bob", "Frank", "Grace", "Alice", "Henry"}
Usando operações de conjunto, encontre:
- Alunos que estão nas duas turmas (reprovaram e repetiram)
- Alunos exclusivos de cada turma
- Total de alunos distintos entre as duas turmas
Checkpoint 5: Escolha de estrutura
Para cada situação, justifique qual estrutura (list, tuple, set ou dict) é mais apropriada:
- Os três colocados em um pódio de corrida (1º, 2º, 3º lugar com nome do atleta)
- Os CPFs de todos os usuários cadastrados num sistema (sem repetição, sem ordem)
- O histórico de páginas visitadas em um navegador (na ordem em que foram abertas)
- As configurações de conexão com banco de dados (host, porta, usuário, senha)
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: Controle de Presença e Aprovação por Frequência
Contexto: Uma disciplina realiza chamada em cada aula. Cada chamada é registrada como um conjunto de alunos presentes naquele dia. A frequência mínima para aprovação é de 75% das aulas realizadas. Os dados de cada aluno também incluem matrícula e nome, armazenados como tuplas.
Código inicial:
alunos = [
("2024001", "Ana"),
("2024002", "Bruno"),
("2024003", "Carlos"),
("2024004", "Diana"),
("2024005", "Eduardo"),
("2024006", "Flávia"),
]
chamadas = [
{"Ana", "Bruno", "Carlos", "Diana"},
{"Ana", "Carlos", "Eduardo", "Flávia"},
{"Ana", "Bruno", "Diana", "Flávia"},
{"Bruno", "Carlos", "Diana"},
{"Ana", "Carlos", "Eduardo"},
{"Ana", "Bruno", "Diana", "Flávia"},
{"Ana", "Carlos", "Diana", "Eduardo"},
{"Bruno", "Diana", "Flávia"},
]
Tarefas:
- Determine quantas aulas cada aluno frequentou.
- Calcule o percentual de frequência e classifique cada aluno como aprovado por frequência (>= 75%) ou reprovado por falta.
- Liste os alunos que nunca compareceram a nenhuma aula.
- Exiba um relatório ordenado por frequência decrescente, com matrícula, nome, presenças e percentual.
Use união de conjuntos para descobrir quem já apareceu em pelo menos uma chamada e sorted(..., key=..., reverse=True) para ordenar o relatório.
Ver solução
TOTAL_AULAS = len(chamadas)
MINIMO = 0.75
presencas = {}
for matricula, nome in alunos:
contagem = 0
for chamada in chamadas:
if nome in chamada:
contagem += 1
presencas[matricula] = contagem
resultado = []
for matricula, nome in alunos:
qtd = presencas[matricula]
perc = qtd / TOTAL_AULAS
if perc >= MINIMO:
situacao = "Aprovado por frequência"
else:
situacao = "Reprovado por falta"
resultado.append((matricula, nome, qtd, perc, situacao))
todos_presentes = set()
for chamada in chamadas:
todos_presentes |= chamada
ausentes = []
for mat, nome in alunos:
if nome not in todos_presentes:
ausentes.append((mat, nome))
# ordenacao manual por percentual (maior para menor)
resultado_ordenado = list(resultado)
for i in range(len(resultado_ordenado)):
indice_maior = i
for j in range(i + 1, len(resultado_ordenado)):
if resultado_ordenado[j][3] > resultado_ordenado[indice_maior][3]:
indice_maior = j
temp = resultado_ordenado[i]
resultado_ordenado[i] = resultado_ordenado[indice_maior]
resultado_ordenado[indice_maior] = temp
for mat, nome, qtd, perc, sit in resultado_ordenado:
print(mat, nome, f"{qtd}/{TOTAL_AULAS}", f"{perc*100:.1f}%", sit)
print("Ausentes sempre:", ausentes)
Situação Problema 2: Análise de Preferências em Pesquisa de Disciplinas
Contexto: Uma pesquisa pediu a cada aluno que indicasse quais disciplinas optativas deseja cursar no próximo semestre. As respostas vieram como listas e podem conter repetições por erro de formulário.
Código inicial:
respostas_brutas = [
(("2024001", "Ana"), ["IA", "redes", "IA", " Banco de Dados", "Compiladores"]),
(("2024002", "Bruno"), ["Redes", "banco de dados", "IA", "Redes"]),
(("2024003", "Carlos"), ["compiladores", "IA", "Redes", "Compiladores"]),
(("2024004", "Diana"), ["banco de dados", " IA", "redes", "Compiladores"]),
(("2024005", "Eduardo"), ["IA", "banco de dados", "IA"]),
]
Tarefas:
- Normalize as respostas removendo duplicatas por aluno e padronizando com
.strip().lower(). - Calcule quantos alunos escolheram cada disciplina e ordene por popularidade (maior para menor).
- Encontre as disciplinas escolhidas por todos os alunos (interseção global).
- Para cada par de alunos, liste as disciplinas em comum (apenas pares com interseção não vazia).
Converta cada lista de respostas em set para simplificar deduplicação e operações de interseção.
Ver solução
preferencias = {}
for aluno_tupla, lista in respostas_brutas:
disciplinas = set()
for d in lista:
disciplinas.add(d.strip().lower())
preferencias[aluno_tupla] = disciplinas
popularidade = {}
for discs in preferencias.values():
for d in discs:
if d not in popularidade:
popularidade[d] = 0
popularidade[d] += 1
# ordenacao manual da popularidade (maior para menor)
popularidade_lista = list(popularidade.items())
for i in range(len(popularidade_lista)):
indice_maior = i
for j in range(i + 1, len(popularidade_lista)):
if popularidade_lista[j][1] > popularidade_lista[indice_maior][1]:
indice_maior = j
temp = popularidade_lista[i]
popularidade_lista[i] = popularidade_lista[indice_maior]
popularidade_lista[indice_maior] = temp
print(popularidade_lista)
sets_lista = list(preferencias.values())
comuns = sets_lista[0]
for s in sets_lista[1:]:
comuns &= s
print("Comuns a todos:", comuns)
alunos_lista = list(preferencias.keys())
for i in range(len(alunos_lista)):
for j in range(i + 1, len(alunos_lista)):
em_comum = preferencias[alunos_lista[i]] & preferencias[alunos_lista[j]]
if em_comum:
print(alunos_lista[i][1], "&", alunos_lista[j][1], sorted(em_comum))
Resumo da Aula
Nesta aula, você aprendeu:
- Tuplas são sequências ordenadas e imutáveis — use quando os dados não devem mudar
- O desempacotamento de tuplas permite atribuir múltiplos valores em uma linha
- Conjuntos armazenam elementos únicos sem ordem — ideal para eliminar duplicatas
- Operações de conjunto (
|,&,-,^) permitem comparar coleções eficientemente - A escolha entre lista, tupla, conjunto e dicionário depende de: mutabilidade, ordem, unicidade e forma de acesso
Próxima aula: Combinando Estruturas de Dados — listas de dicionários e outras composições para modelar dados complexos
Referências
Leitura Essencial
- Python Software Foundation. Sequence Types — tuple. Disponível em: docs.python.org/3/library/stdtypes.html#tuple
- Python Software Foundation. Set Types — set, frozenset. Disponível em: docs.python.org/3/library/stdtypes.html#set-types-set-frozenset
- Documentação oficial de tuplas e conjuntos com todos os métodos disponíveis.
Aprofundamento (Opcional)
- Python Software Foundation. frozenset. Disponível em: docs.python.org/3/library/stdtypes.html#frozenset
- Variante imutável do conjunto — pode ser usada como chave de dicionário.
- Lutz, M. Aprendendo Python. 5ª ed. São Paulo: O'Reilly Brasil, 2013.
- Capítulo sobre tipos de sequências aprofunda as distinções entre listas, tuplas e conjuntos com exemplos avançados.