Em Python, existem dois grandes grupos de estruturas de dados iteráveis: sequências e coleções baseadas em hash. Cada um tem características distintas que afetam diretamente o desempenho das operações, especialmente em buscas e comparações.
Sequências vs. Estruturas Baseadas em Hash
As sequências — como listas, tuplas e strings — armazenam elementos em posições contíguas na memória. Isso significa que, ao procurar um valor específico, o interpretador precisa percorrer os itens um a um até encontrar uma correspondência. Esse processo resulta em complexidade de tempo O(n), tornando a busca ineficiente para grandes volumes de dados.
Já as estruturas baseadas em hash — como dicionários (dict) e conjuntos (set) — utilizam algoritmos de dispersão (hashing) para calcular a posição exata de cada elemento. Assim, tanto a inserção quanto a recuperação ocorrem em tempo constante, O(1), independentemente do tamanho da coleção. Essa eficiência é o grande diferencial desses tipos.
Requisitos de Imutabilidade para Hashing
Para que o hash funcione corretamente, os elementos usados como chaves precisma ser imutáveis. Em Python, isso inclui tipos como None, números (inteiros, flutuantes, booleanos), strings e tuplas compostas apenas por valores imutáveis. Tipos mutáveis, como listas, dicionários ou conjuntos, não podem ser usados como chaves porque sua alteração mudaria o valor do hash, comprometendo a integridade da estrutura.
Dicionários: Mapeamento Chave-Valor Efiicente
O dicionário é um exemplo clássico de tabela de dispersão. Ele permite armazenar pares chave-valor com acesso rápido à informação. Veja alguns exemplos válidos:
d1 = {"nome": "Ana", "idade": 28}
d2 = {42: "resposta", 3.14: "pi"}
d3 = {(1, 2): "coordenada", (3, 4): "outro ponto"}
d4 = {True: "sim", False: "não", None: "desconhecido"}
Todos esses são aceitáveis porque as chaves são imutáveis e, portanto, passíveis de hashing.
Conjuntos: Coleções de Elementos Únicos
Quando não é necessário armazenar valores associados, mas apenas garantir a presença de elementos únicos, o tipo set é ideal. Um conjunto descarta duplicatas automatticamente e oferece operações matemáticas nativas entre coleções.
s = {"maçã", "banana", "laranja"}
print(type(s)) # <class 'set'>
É importante destacar que usar {} cria um dicionário vazio. Para inicializar um conjunto vazio, deve-se usar set().
Aplicações Práticas com Conjuntos
Embora menos comuns no dia a dia, os conjuntos resolvem problemas com elegância e eficiência.
Remoção de Duplicatas em Listas
Uma forma rápida de eliminar repetições em uma lista é convertê-la para conjunto e depois retornar para lista. Note que a ordem original pode não ser preservada.
numeros = [5, 2, 8, 2, 1, 5, 9, 8]
unicos = list(set(numeros))
# Resultado: [1, 2, 5, 8, 9] (ordem não garantida)
Operações Matemáticas entre Coleções
Dado dois grupos de nomes:
grupo_a = ["Carlos", "Mariana", "Rafael", "Julia", "Pedro"]
grupo_b = ["Julia", "Pedro", "Fernanda", "Tiago", "Mariana"]
Pode-se transformar ambos em conjuntos e aplicar operações diretas:
A = set(grupo_a)
B = set(grupo_b)
# União: todos os elementos presentes em qualquer grupo
todos = A | B
# {'Carlos', 'Mariana', 'Rafael', 'Julia', 'Pedro', 'Fernanda', 'Tiago'}
# Interseção: elementos comuns aos dois grupos
comuns = A & B
# {'Mariana', 'Julia', 'Pedro'}
# Diferença: elementos em A que não estão em B
somente_a = A - B
# {'Carlos', 'Rafael'}
Usando Chaves e Itens de Dicionários como Conjuntos
Os métodos .keys() e .items() retornam objetos que suportam operações de conjunto, desde que os valores envolvidos sejam imutáveis.
dados_2023 = {
"receita": 15000,
"despesa": 9000,
"funcionarios": 12,
"local": "SP"
}
dados_2024 = {
"receita": 18000,
"despesa": 9000,
"funcionarios": 15,
"projeto": "expansao"
}
Comparando as chaves:
# Chaves novas em 2024
novas = dados_2024.keys() - dados_2023.keys()
# {'projeto'}
# Chaves ausentes em 2024
perdidas = dados_2023.keys() - dados_2024.keys()
# {'local'}
Comparando pares completos (chave-valor):
alteracoes = dados_2024.items() - dados_2023.items()
# {('receita', 18000), ('funcionarios', 15), ('projeto', 'expansao')}
Essa técnica é útil para detectar mudanças entre versões de configurações, registros ou estados de sistemas.
Restrição Importante
A operação com .items() só é segura quando os valores do dicionário forem imutáveis. Se houver listas, dicionários aninhados ou outros objetos mutáveis, o Python levantará um erro de tipo, pois eles não são passíveis de hash.