Dicionários e Conjuntos
Nas últimas duas lições cobrimos listas e tuplas, que são acessadas "por posição." Mas na vida real, frequentemente buscamos coisas "por nome" — dicionários pela palavra, contatos pelo nome. Dicionários (dict) lidam com isso. Conjuntos (set) são para operações matemáticas de conjuntos. Ambos são extremamente úteis no processamento de dados.
1. O que é um Dicionário
Um dicionário é definido com chaves {}, contendo um conjunto de pares chave-valor, separados por dois pontos.
# Define um dicionário
student = {
"name": "Alice",
"age": 20,
"city": "São Paulo"
}
print(student) # {'name': 'Alice', 'age': 20, 'city': 'São Paulo'}
print(type(student)) # <class 'dict'>
Operações CRUD Básicas
# Cria um dicionário
user = {}
# Adiciona / modifica pares chave-valor
user["name"] = "Alice"
user["age"] = 25
print(user) # {'name': 'Alice', 'age': 25}
# Modifica uma chave existente
user["age"] = 26
print(user) # {'name': 'Alice', 'age': 26}
# Lê um valor
print(user["name"]) # Alice
# print(user["email"]) # KeyError! Chave inexistente levanta erro
# Use get() para acesso seguro — retorna padrão se chave não existe
print(user.get("email")) # None — não encontrado, retorna None
print(user.get("email", "não definido")) # não definido — padrão personalizado
# Remove um par chave-valor
del user["age"]
print(user) # {'name': 'Alice'}
dict["chave_inexistente"] levanta KeyError. Use get() para evitar isso — retorna None ou seu padrão especificado.
Exemplo: Gerenciamento de Informações de Aluno (Dificuldade ⭐)
# Armazena informações completas de um aluno em um dicionário
student = {
"name": "Bob",
"id": "2024001",
"scores": {"Português": 85, "Matemática": 92, "Inglês": 78},
"is_active": True
}
# Lê informações básicas
print(f"Nome: {student['name']}")
print(f"ID: {student['id']}")
# Lê de dicionário aninhado
math_score = student["scores"]["Matemática"]
print(f"Nota de Matemática: {math_score}")
# Acesso seguro com get
phone = student.get("phone", "não preenchido")
print(f"Telefone: {phone}")
Saída:
Nome: Bob
ID: 2024001
Nota de Matemática: 92
Telefone: não preenchido
2. Métodos Comuns de Dicionário
Obtendo Todas as Chaves, Valores e Pares Chave-Valor
user = {"name": "Alice", "age": 25, "city": "São Paulo"}
print(user.keys()) # dict_keys(['name', 'age', 'city'])
print(user.values()) # dict_values(['Alice', 25, 'São Paulo'])
print(user.items()) # dict_items([('name', 'Alice'), ('age', 25), ('city', 'São Paulo')])
# Forma mais comum de iterar um dicionário
for key, value in user.items():
print(f"{key} = {value}")
Saída:
name = Alice
age = 25
city = São Paulo
pop() e setdefault()
# pop() — remove e retorna o valor de uma chave
user = {"name": "Alice", "age": 25, "city": "São Paulo"}
city = user.pop("city")
print(f"Cidade removida: {city}") # Cidade removida: São Paulo
print(user) # {'name': 'Alice', 'age': 25}
# pop() pode especificar um padrão, evitando KeyError
email = user.pop("email", "sem email")
print(email) # sem email — chave não existe, retorna padrão
# setdefault() — se chave existe, retorna seu valor; se não, insere o padrão
user = {"name": "Alice"}
result = user.setdefault("age", 18)
print(user) # {'name': 'Alice', 'age': 18}
# Se chave já existe, setdefault não a modifica
result = user.setdefault("name", "Bob")
print(user) # {'name': 'Alice', 'age': 18} — inalterado
update() — Mesclando Dicionários
# Mescla dois dicionários
defaults = {"theme": "light", "lang": "pt", "font_size": 14}
custom = {"theme": "dark", "font_size": 16}
defaults.update(custom) # custom sobrescreve chaves correspondentes em defaults
print(defaults) # {'theme': 'dark', 'lang': 'pt', 'font_size': 16}
Exemplo: Contagem de Palavras (Dificuldade ⭐⭐)
# Conta ocorrências de palavras em uma frase
text = "maçã banana maçã laranja banana maçã"
word_count = {}
for word in text.split():
# Se palavra já está no dict, incrementa; senão, define como 1
word_count[word] = word_count.get(word, 0) + 1
print(word_count) # {'maçã': 3, 'banana': 2, 'laranja': 1}
# Saída com items()
for word, count in word_count.items():
print(f"{word}: {count} vezes")
Saída:
maçã: 3 vezes
banana: 2 vezes
laranja: 1 vezes
3. Iteração e Aninhamento de Dicionários
Três Formas de Iterar um Dicionário
user = {"name": "Alice", "age": 25, "city": "São Paulo"}
# Método 1: iterar sobre chaves
for key in user: # Equivalente a for key in user.keys():
print(f"{key}: {user[key]}")
# Método 2: iterar sobre valores
for value in user.values():
print(value)
# Método 3: iterar sobre pares chave-valor (recomendado)
for key, value in user.items():
print(f"{key} → {value}")
Dicionários Aninhados
# Dicionário aninhado — armazenando múltiplos registros de alunos
students = {
"1001": {"name": "Alice", "scores": [85, 90, 78]},
"1002": {"name": "Bob", "scores": [92, 88, 95]},
"1003": {"name": "Charlie", "scores": [76, 85, 82]},
}
# Iterar sobre dicionário aninhado
for sid, info in students.items():
name = info["name"]
avg = sum(info["scores"]) / len(info["scores"])
print(f"{sid} {name}: Média {avg:.1f}")
Saída:
1001 Alice: Média 84.3
1002 Bob: Média 91.7
1003 Charlie: Média 81.0
4. O que é um Conjunto (Set)
Um conjunto é definido com chaves {} ou set(). Parece um dicionário mas não tem valores, apenas chaves. Conjuntos são: elementos únicos, não ordenados.
# Define um conjunto
fruits = {"maçã", "banana", "laranja", "maçã"} # Duplicatas são removidas automaticamente
print(fruits) # {'laranja', 'maçã', 'banana'} — ordem pode variar
# Cria um conjunto a partir de uma lista
numbers = set([1, 2, 2, 3, 3, 3])
print(numbers) # {1, 2, 3} — duplicatas removidas
# Conjunto vazio deve usar set(), não {} ({} é um dict vazio)
empty_set = set()
print(type(empty_set)) # <class 'set'>
list(set(lista)) remove duplicatas rapidamente. Mas observe que conjuntos não são ordenados, então a ordem original é perdida.
Operações Básicas de Conjunto
# Adicionar e remover
s = set()
s.add("maçã")
s.add("banana")
s.add("maçã") # Adicionar duplicata não tem efeito
print(s) # {'maçã', 'banana'}
s.discard("maçã") # Remove; não dá erro se não encontrado
print(s) # {'banana'}
# s.remove("inexistente") # Levantaria KeyError!
5. Operações com Conjuntos
É aqui que os conjuntos realmente brilham — interseção, união e diferença matemáticas:
a = {1, 2, 3, 4, 5}
b = {4, 5, 6, 7, 8}
# Interseção — elementos presentes em ambos os conjuntos
print(a & b) # {4, 5}
print(a.intersection(b)) # Mesmo
# União — todos os elementos de ambos (sem duplicatas)
print(a | b) # {1, 2, 3, 4, 5, 6, 7, 8}
print(a.union(b)) # Mesmo
# Diferença — elementos em a mas não em b
print(a - b) # {1, 2, 3}
print(a.difference(b)) # Mesmo
# Diferença simétrica — elementos em a ou b mas não em ambos
print(a ^ b) # {1, 2, 3, 6, 7, 8}
Exemplo: Análise de Permissões de Usuário (Dificuldade ⭐⭐⭐)
# Simula relacionamentos de usuários em uma plataforma social
all_users = {"Alice", "Bob", "Charlie", "Diana", "Eve"}
vip_users = {"Bob", "Diana", "Eve"}
blocked_users = {"Diana"}
# Encontra "usuários normais que não são VIP"
normal_users = all_users - vip_users - blocked_users
print(f"Usuários normais: {normal_users}")
# Encontra "VIPs ativos (não bloqueados)"
active_vip = vip_users - blocked_users
print(f"VIPs ativos: {active_vip}")
# Encontra "usuários bloqueados que são VIP"
blocked_vip = vip_users & blocked_users
print(f"VIPs bloqueados: {blocked_vip}")
# Encontra "todos os usuários que precisam de notificação (VIPs + bloqueados)"
notify_users = vip_users | blocked_users
print(f"Usuários para notificar: {notify_users}")
Saída:
Usuários normais: {'Alice', 'Charlie'}
VIPs ativos: {'Bob', 'Eve'}
VIPs bloqueados: {'Diana'}
Usuários para notificar: {'Bob', 'Diana', 'Eve'}
Casos de Uso Comuns
- Gerenciamento de configuração: Armazene parâmetros de configuração (chave=nome da configuração, valor=valor); use
get()com padrões. - Contagem de frequência: Use dict como contador —
dict[chave] = dict.get(chave, 0) + 1para cada ocorrência. - Agrupamento de dados: Dicts aninhados
{"departamento": [lista_funcionarios]}para agrupar por departamento. - Deduplicação: Set remove duplicatas automaticamente;
list(set(data))para dedup rápido (sem ordem);dict.fromkeys(data)para dedup com ordem. - Verificações de permissão: Operações de conjunto para interseção (permissões sobrepostas) e diferença (permissões faltantes).
❓ Perguntas Frequentes
P: Quando devo usar um dicionário vs uma lista? R: Se você está buscando dados por "nome" (chave), use um dicionário — ex.: buscar um aluno por ID. Se você só precisa acessar dados "sequencialmente," use uma lista — ex.: um carrinho de compras. A busca em dicionários é muito mais rápida que em listas — a diferença é significativa com grandes conjuntos de dados (milhares de itens). ⚠️ P: Quais restrições as chaves de dicionário têm? Por que listas não podem ser chaves? R: Chaves de dicionário devem ser imutáveis — números, strings e tuplas funcionam. Listas são mutáveis, então não podem ser chaves. Se uma lista fosse chave e seu conteúdo mudasse, o dicionário não seria capaz de encontrá-la. Esta é a mesma razão pela qual tuplas podem ser chaves — são imutáveis, então são seguras. P: Qual a diferença entre
discard()eremove()? R:remove()levantaKeyErrorse o elemento não existir.discard()não — remove se presente, ou silenciosamente não faz nada se não estiver. Se você não tem certeza se um elemento existe, usediscard()por segurança.
📖 Resumo
- Dicionários usam
{}, armazenam pares chave-valor, e buscam valores por chave rapidamente - Operações básicas:
dict[chave]ler/escrever,get()leitura segura,deldeletar - Métodos comuns:
keys(),values(),items()para iteração;pop()remover e retornar;update()mesclar setdefault()retorna valor existente ou insere um padrão- Valores de dicionário podem ser de qualquer tipo, incluindo listas e dicts — permitindo estruturas aninhadas
- Conjuntos usam
{}ouset(), únicos e não ordenados, principalmente para deduplicação e operações matemáticas - Operações de conjunto:
&interseção,|união,-diferença,^diferença simétrica
📝 Atividades
-
Básico (Dificuldade ⭐): Crie um dicionário com suas informações pessoais (nome, idade, cidade, hobby). Use
get()para ler um campo "profissão" (retorne "não preenchido" se faltar). Useitems()para exibir todos os pares chave-valor. -
Intermediário (Dificuldade ⭐⭐): Dada a frase
"hello world hello python world hello", conte as ocorrências de cada palavra e encontre a palavra mais frequente. Dica: Use um dicionário para contagem; usemax(dict.items(), key=lambda x: x[1])para encontrar o máximo. -
Desafio (Dificuldade ⭐⭐⭐): Escreva um programa "Agenda de Contatos Simples." Use um dicionário (nome → telefone). Suporte:
add Alice 13800138000,del Alice,find Alice,all(listar todos). Usewhile True;exitpara sair. Dica: Usesplit()para analisar comandos.



