🇯🇵 日本語 | 🇺🇸 English | 🇪🇸 Español | 🇵🇹 Português | 🇹🇭 ไทย | 🇨🇳 中文

Chega de sofrer com KeyError! Eleve seu código com o módulo collections do Python

Para executar Python no prompt de comando ou PowerShell no seu PC, é necessário baixar e instalar o Python.
Se ainda não o fez, consulte o artigo Instalação do Python e configuração do ambiente de desenvolvimento para instalar o Python.

Olá! Sou eu, a pessoa que, com uma ajudinha da IA, construiu dois sites do zero com apenas alguns meses de programação.

Hoje, vou explicar de uma forma bem simples o superútil módulo "collections" do Python, um recurso que eu realmente gostaria de ter conhecido antes na minha jornada de aprendizado. Vou compartilhar até algumas das minhas próprias falhas no processo.

Este artigo será especialmente útil se você já sofreu com o erro `KeyError` em dicionários (`dict`) ou sentiu que suas operações com listas (`list`) estão um pouco lentas. Ao final da leitura, seu código Python certamente estará muito mais inteligente! Evitei jargões técnicos e preparei vários códigos prontos para copiar e colar, então vamos juntos experimentar e fazer as coisas "funcionarem"!


Afinal, o que é o módulo collections?

A palavra "módulo" pode parecer complicada, mas pense nela como uma "caixa de ferramentas útil que já vem com o Python". Você não precisa instalar nada extra; basta escrever uma única linha com `import` e você está pronto para usar.

Dentro desta caixa de ferramentas, você encontrará utilitários especiais que tornam as estruturas de dados básicas do Python, como `dict` (dicionários) e `list` (listas), ainda mais poderosas e fáceis de usar. Neste artigo, vou focar em duas ferramentas que achei particularmente impressionantes: `defaultdict` e `deque`.


`defaultdict`: A caixa mágica que evita erros de desatenção em dicionários

A luta sem o `defaultdict`... (Minha história de fracasso)

Você já esteve usando um dicionário (`dict`) e se deparou com um erro como este?

# Tentando acessar uma chave inexistente em um dicionário comum
word_counts = {}
# A chave 'apple' ainda não existe
word_counts['apple'] += 1 # Erro aqui!

# Resultado da Execução
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# KeyError: 'apple'

Este é um `KeyError`, que é a maneira do Python dizer: "Ei, essa chave não existe no dicionário!". Quando eu estava construindo meus sites, passei horas preso nesse erro ao tentar processar dados de entrada do usuário.

Você pode prevenir este erro verificando se uma chave existe com uma instrução `if` ou usando o método `get()`, mas isso torna o código um pouco mais longo, não é?


Eis que surge o salvador: `defaultdict`!

`defaultdict` é o que resolve este problema de `KeyError` de uma só vez. É um dicionário mágico que "cria automaticamente um 'valor padrão' quando você acessa uma chave inexistente."

Ver para crer. Vamos dar uma olhada no código.

from collections import defaultdict

# Cria um defaultdict onde o valor padrão é 0, especificando int
word_counts = defaultdict(int)

# A chave 'apple' ainda não existe... mas tudo bem!
print(f"Antes do acesso: {word_counts}") # Está vazio antes do acesso
word_counts['apple'] += 1 # Sem erro! Ele cria automaticamente word_counts['apple'] = 0 e depois incrementa em 1
print(f"Depois do acesso: {word_counts}")
print(f"Contagem de maçãs: {word_counts['apple']}")
print(f"Contagem de laranjas: {word_counts['orange']}") # 'orange' também não existe, mas acessá-la retorna o valor padrão 0

Bem legal, né? Ao escrever `defaultdict(int)`, você está dizendo: "Se uma chave não existir, por favor, defina automaticamente seu valor inicial como `int()`, que é `0`." Isso permite que você comece a fazer cálculos imediatamente sem se preocupar com um `KeyError`.
Este comportamento é descrito na documentação oficial do Python como "retorna um valor padrão para uma chave inexistente", tornando-o um recurso muito confiável.


[Pronto para Copiar e Colar] Exemplo de Aplicação: Contando Ocorrências de Palavras em um Texto

`defaultdict` é especialmente útil quando você precisa contar coisas. Por exemplo, você pode contar facilmente quantas vezes cada palavra aparece em um texto, assim:

from collections import defaultdict

sentence = "apple banana apple orange banana apple"
words = sentence.split() # Divide a frase em uma lista de palavras

# Um defaultdict onde o valor padrão é 0, especificando int
word_counts = defaultdict(int)

for word in words:
  word_counts[word] += 1

# Exibe os resultados
for word, count in word_counts.items():
  print(f"'{word}': {count} vezes")

# Você também pode convertê-lo para um dict comum para verificar o conteúdo
print(f"\nConteúdo final do dicionário: {dict(word_counts)}")

Tente copiar, colar e executar este código. Você verá que ele conta as palavras com precisão sem uma única instrução `if`. Esse é o poder do `defaultdict`!


`deque`: A fila de alta velocidade que resolve a "lentidão" das listas

Adicionar/Remover do início de uma lista é, na verdade, ineficiente

O próximo é o `deque` (pronuncia-se "dék"). É muito semelhante a uma lista (`list`), mas tem um recurso especial: é incrivelmente rápido para adicionar e remover elementos do início.

A verdade é que, enquanto a `list` do Python é boa para adicionar ao final (lado direito) com `append`, ela não é muito boa para adicionar ao início (lado esquerdo) com `insert(0, ...)` ou remover dele com `pop(0)`.

Isso porque, quando você adiciona ou remove um elemento no início de uma lista, todos os elementos subsequentes precisam ser deslocados um por um. É como entrar no meio de uma longa fila de pessoas ou a pessoa da frente sair — todos atrás dela precisam se mover. Quanto mais elementos houver, mais trabalhoso se torna esse "deslocamento" e mais lento fica o processo.


Deixe as operações de ambas as extremidades para o `deque`!

`deque` foi criado para resolver exatamente este problema. Ele usa uma estrutura interna inteligente (chamada de lista duplamente encadeada) que torna a adição ou remoção de itens de qualquer uma das extremidades uma operação instantânea, não importa quantos elementos existam.

Vamos ver isso em código também. Operações que você faria com uma lista podem ser feitas com um `deque` usando nomes de método mais intuitivos e de forma muito mais rápida.

from collections import deque

# Criar um deque
tasks = deque(['task2', 'task3'])
print(f"Estado inicial: {tasks}")

# Adicionar ao final (o mesmo que o append da lista)
tasks.append('task4')
print(f"Adicionado ao final: {tasks}")

# Adicionar ao início (mais rápido que o insert(0,...) da lista)!
tasks.appendleft('task1')
print(f"Adicionado ao início: {tasks}")

# Remover do início (mais rápido que o pop(0) da lista)!
first_task = tasks.popleft()
print(f"Tarefa removida do início: {first_task}")
print(f"Estado atual: {tasks}")

[Pronto para Copiar e Colar] Exemplo de Aplicação: Lista de Itens Vistos Recentemente (com Limite Máximo)

`deque` é extremamente útil para gerenciar tarefas ou históricos. Com seu recurso `maxlen`, você pode criar facilmente uma lista que "sempre mantém apenas os últimos N itens".

Imagine um recurso de "Itens Vistos Recentemente" em um site de e-commerce.

from collections import deque
import time

# Cria um deque que armazena no máximo 5 itens de histórico
history = deque(maxlen=5)

products = ['Camiseta', 'Tênis', 'Boné', 'Moletom', 'Jaqueta', 'Shorts']

for product in products:
  print(f"Visualizando '{product}'.")
  history.append(product)
  print(f"Histórico de visualização atual: {list(history)}") # Converter para list() torna a visualização mais fácil
  time.sleep(1) # espere por 1 segundo

print("\n--- Histórico de Visualização Final (Últimos 5 Itens) ---")
for item in history:
  print(item)

Ao executar este código, você verá que, à medida que um novo item é adicionado, o mais antigo é automaticamente empurrado para fora e desaparece. Se você fosse implementar isso por conta própria com uma `list`, precisaria de uma verificação como `if len(list) > 5:`, mas com `deque(maxlen=N)`, isso não é necessário. Inteligente, não é?


[Experimente!] Um Contador de Palavras que Roda no seu Navegador

Preparei um exemplo para que você possa experimentar a conveniência do `defaultdict` agora mesmo no seu navegador. Copie todo o código HTML abaixo, cole-o em um editor de texto e salve-o com um nome como "teste.html". Em seguida, abra esse arquivo no seu navegador.

Este não é um código Python, mas reproduz o conceito do `defaultdict` de "inicializar automaticamente um valor mesmo que a chave não exista" usando JavaScript. Tente inserir algum texto na área de texto e pressionar o botão!

<!DOCTYPE html>
<html lang="pt">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Demo do Contador de Palavras</title>
  <style>
    body { font-family: sans-serif; background-color: #202124; color: #e8eaed; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; }
    .container { width: 90%; max-width: 600px; padding: 2rem; border: 1px solid #5f6368; border-radius: 8px; }
    h1 { color: #669df6; }
    textarea { width: 100%; height: 150px; background-color: #3c4043; color: #e8eaed; border: 1px solid #5f6368; border-radius: 4px; padding: 10px; font-size: 1rem; margin-bottom: 1rem; }
    button { background-color: #8ab4f8; color: #202124; border: none; padding: 10px 20px; border-radius: 4px; cursor: pointer; font-weight: bold; }
    button:hover { opacity: 0.9; }
    #result { margin-top: 1.5rem; background-color: #282a2d; padding: 1rem; border-radius: 4px; }
    pre { white-space: pre-wrap; word-wrap: break-word; }
  </style>
</head>
<body>
  <div class="container">
    <h1>Contador de Palavras</h1>
    <p>Insira o texto na caixa abaixo e pressione o botão.</p>
    <textarea id="text-input" placeholder="Insira o texto aqui... (ex: maçã banana maçã laranja)"></textarea>
    <button onclick="countWords()">Contar Palavras</button>
    <div id="result">
      <pre>Os resultados serão exibidos aqui.</pre>
    </div>
  </div>

  <script>
    function countWords() {
      const text = document.getElementById('text-input').value;
      const resultEl = document.getElementById('result');

      if (!text.trim()) {
        resultEl.innerHTML = '<pre>Nenhum texto inserido.</pre>';
        return;
      }

      // Divide em palavras por espaços ou novas linhas e remove elementos vazios
      const words = text.toLowerCase().match(/\b(\w+)\b/g) || [];

      // Imita o comportamento do defaultdict(int)
      const counts = {}; 
      for (const word of words) {
        // Se a chave não existir, define como 0 e depois incrementa
        counts[word] = (counts[word] || 0) + 1;
      }

      // Formata e exibe o resultado
      let resultText = '[Resultado da Contagem]\n';
      for (const [word, count] of Object.entries(counts)) {
        resultText += `"${word}": ${count} vezes\n`;
      }
      
      resultEl.innerHTML = `<pre>${resultText}</pre>`;
    }
  </script>
</body>
</html>

Pontos a Observar ao Usar `collections`

Finalmente, deixe-me abordar alguns pequenos pontos a serem lembrados ao usar essas ferramentas úteis.


Resumo: Programe de Forma Mais Inteligente e Leve sua Programação para o Próximo Nível

Neste artigo, apresentamos `defaultdict` e `deque` do módulo padrão "collections" do Python, duas ferramentas que são especialmente úteis para se conhecer desde os estágios iniciais de aprendizado.

Desde que aprendi sobre estes, meu próprio código se tornou mais simples, e o tempo que passo depurando erros diminuiu drasticamente. Encorajo você a começar copiando e colando o código deste artigo para experimentar sua conveniência por si mesmo. Embora dominar o `list` e `dict` básicos seja importante, usar ferramentas úteis como as do `collections` nos lugares certos o ajudará a escrever um código mais eficiente e legível!

Próximos Passos

Agora que você experimentou a conveniência do módulo `collections`, por que não tentar construir uma aplicação baseada em texto? Vamos aproveitar a diversão de criar algo que funcione usando estruturas de dados básicas!

Vamos Construir um App de Lista de Tarefas em Python (Baseado em Texto)