Módulo 5 - Módulos e a biblioteca padrão

Coleções especiais: Counter, defaultdict e namedtuple

11 min de leitura · por Cesar Gargiulo, revisado pela equipe ValorFinal e GuardiaSec · Atualizado em 01/07/2026

O que você vai aprender

  • Contar ocorrências automaticamente com Counter.
  • Evitar o erro de chave inexistente com defaultdict.
  • Dar nomes aos campos de uma tupla com namedtuple.
  • Reconhecer quando cada uma dessas coleções deixa o código mais limpo.

Counter: contar sem esforço

O módulo collections oferece versões especializadas das estruturas de dados que você já usa. Não são substitutos do dia a dia, e sim atalhos poderosos para situações comuns. O primeiro e talvez mais amado é o Counter. Contar ocorrências, quantas vezes cada palavra aparece num texto, quantas vezes cada nota se repete, é uma tarefa que você faria com um dicionário e um laço. O Counter faz tudo isso em uma linha.

from collections import Counter

votos = ["a", "b", "a", "c", "a", "b"]
contagem = Counter(votos)
print(contagem)            # Counter({'a': 3, 'b': 2, 'c': 1})
print(contagem["a"])       # 3

# os mais comuns, ja ordenados do maior para o menor
print(contagem.most_common(2))   # [('a', 3), ('b', 2)]

Counter conta cada item de uma vez e most_common já entrega ordenado.

Contando na mão

  • Cria um dicionário vazio antes
  • Percorre a sequência com um laço
  • Testa se a chave já existe a cada item
  • Umas cinco linhas para o mesmo resultado

Contando com Counter

  • Uma linha: Counter(sequencia)
  • Já vem com most_common pronto
  • Não precisa testar chave nenhuma
  • Código curto e óbvio de ler

defaultdict: adeus KeyError

Um tropeço clássico com dicionários é acessar uma chave que ainda não existe e levar um erro, o KeyError. Isso acontece muito quando você agrupa itens: quer juntar valores por categoria, mas na primeira vez que uma categoria aparece, a chave não existe ainda. Com um dicionário normal, você precisa testar se a chave existe antes de usar. O defaultdict elimina esse teste: ao acessar uma chave nova, ele já cria a chave com um valor padrão que você escolhe.

from collections import defaultdict

# agrupar nomes pela primeira letra
nomes = ["Ana", "Bruno", "Alice", "Carlos", "Bia"]
grupos = defaultdict(list)   # cada chave nova comeca como lista vazia

for nome in nomes:
    inicial = nome[0]
    grupos[inicial].append(nome)   # sem KeyError, mesmo na primeira vez

print(dict(grupos))
# {'A': ['Ana', 'Alice'], 'B': ['Bruno', 'Bia'], 'C': ['Carlos']}

defaultdict(list) cria uma lista vazia na primeira vez que a chave aparece.

Repare que passamos list, sem os parênteses, para o defaultdict. Isso diz a ele: quando uma chave nova aparecer, crie uma lista vazia para ela. Se quiséssemos somar números por categoria, usaríamos defaultdict(int), que começa cada chave em zero. O padrão é sempre o mesmo: escolha o tipo do valor inicial e o defaultdict cuida do resto, sem você precisar testar a existência de cada chave. O código fica mais curto e sem o risco do KeyError.

namedtuple: tuplas com nome

A terceira ferramenta resolve um incômodo das tuplas: acessar os campos por número é confuso. Se ponto = (10, 20), o que é ponto[0]? A coordenada x, mas nada no código diz isso. A namedtuple cria um tipo de tupla em que cada posição tem um nome. Você acessa ponto.x e ponto.y, e fica óbvio. É uma forma leve de agrupar dados relacionados sem escrever uma classe inteira, um meio-termo entre a tupla crua e a orientação a objetos que vem mais à frente.

from collections import namedtuple

# cria um tipo Ponto com os campos x e y
Ponto = namedtuple("Ponto", ["x", "y"])

p = Ponto(10, 20)
print(p.x)     # 10
print(p.y)     # 20
print(p)       # Ponto(x=10, y=20)

# continua sendo uma tupla: da para desempacotar
x, y = p
print(x + y)   # 30

namedtuple dá nomes aos campos, mas o objeto continua sendo uma tupla de verdade.

A namedtuple é o melhor dos dois mundos: você acessa por nome, o que deixa o código legível, e o objeto continua sendo uma tupla, então pode ser desempacotado e é imutável, o que evita alterações acidentais. Ela brilha para registros pequenos e fixos, como um ponto, uma cor RGB ou uma linha de planilha. Quando os dados precisam de comportamento além de guardar valores, aí sim entra uma classe, tema dos módulos de orientação a objetos. Por enquanto, você tem três atalhos que enxugam bastante código do dia a dia.

Teste rápido

Qual coleção do módulo collections conta ocorrências automaticamente?

Perguntas frequentes

Counter é um dicionário de verdade?
É uma subclasse de dicionário, então funciona como um: você acessa contagem["a"] normalmente. A diferença é que ele conta sozinho ao receber uma sequência e traz extras, como most_common. Uma chave que nunca apareceu devolve 0 no Counter, em vez de dar erro.
Quando uso defaultdict em vez de um dicionário normal?
Quando você agrupa ou acumula valores por chave e quer evitar testar se a chave já existe a cada item. defaultdict(list) para agrupar em listas, defaultdict(int) para somar ou contar. Se você raramente acessa chaves inexistentes, um dicionário comum já basta.
Por que passo list sem parênteses no defaultdict?
Porque o defaultdict quer o tipo que ele vai usar para criar o valor padrão, não um valor já pronto. Ele mesmo chama list() quando precisa. Passar list() com parênteses criaria uma única lista e não funcionaria como padrão. Vale o mesmo para int, dict e set.
namedtuple é a mesma coisa que uma classe?
É um meio-termo. Ela agrupa dados com campos nomeados, como uma classe simples, mas sem comportamento e sendo imutável, como uma tupla. Para registros pequenos e fixos, é mais leve que escrever uma classe. Quando os dados precisam de métodos, aí vale a classe completa, vista adiante no curso.
Preciso decorar os três agora?
Não. O importante é saber que eles existem e reconhecer a situação: contar ocorrências pede Counter, agrupar sem KeyError pede defaultdict, tupla com campos nomeados pede namedtuple. Quando bater a situação, você consulta a sintaxe. Programador consulta a documentação o tempo todo.
O most_common devolve os itens em qual ordem?
Do mais frequente para o menos frequente. most_common(2) devolve os dois itens que mais aparecem, cada um como uma tupla de item e contagem, já ordenados. Sem argumento, most_common() devolve todos os itens ordenados por frequência.

Fontes

Seu progresso fica salvo neste aparelho. Assinantes sincronizam entre os aparelhos.