Pular para o conteúdo

Como Usar defaultdict no Python?

[

Usando o tipo defaultdict do Python para lidar com chaves ausentes

Um problema comum ao trabalhar com dicionários em Python é tentar acessar ou modificar chaves que não existem no dicionário. Isso geralmente resulta em um KeyError e interrompe a execução do código. Para lidar com esse tipo de situação, a biblioteca padrão do Python disponibiliza o tipo defaultdict, uma classe semelhante a um dicionário que está disponível no módulo collections.

O tipo defaultdict do Python se comporta quase exatamente como um dicionário Python regular, mas se você tentar acessar ou modificar uma chave que não exista, o defaultdict automaticamente criará a chave e gerará um valor padrão para ela. Isso torna o defaultdict uma opção valiosa para lidar com chaves ausentes em dicionários.

Neste tutorial, você aprenderá:

  • Como usar o tipo defaultdict do Python para lidar com chaves ausentes em um dicionário.
  • Quando e por que usar um defaultdict em vez de um dicionário regular.
  • Como usar um defaultdict para operações de agrupamento, contagem e acumulação de valores.

Com esse conhecimento, você estará melhor preparado para usar efetivamente o tipo defaultdict do Python em seus desafios de programação diários.

Lidando com chaves ausentes em dicionários

Um problema comum ao trabalhar com dicionários em Python é lidar com chaves ausentes. Se o seu código é baseado principalmente em dicionários ou se você está criando dicionários com frequência, logo perceberá que lidar com exceções frequentes de KeyError pode ser bastante irritante e adicionar complexidade extra ao seu código. Com os dicionários do Python, existem pelo menos quatro maneiras de lidar com chaves ausentes:

  1. Usando o método get() para acessar uma chave e retornar um valor padrão se a chave não existir:
my_dict = {"a": 1, "b": 2}
print(my_dict.get("c", 0)) # 0
  1. Usando o método setdefault() para definir um valor padrão para uma chave se a chave não existir:
my_dict = {"a": 1, "b": 2}
my_dict.setdefault("c", 0)
print(my_dict) # {'a': 1, 'b': 2, 'c': 0}
  1. Usando condicionais para verificar se uma chave existe antes de acessá-la:
my_dict = {"a": 1, "b": 2}
if "c" in my_dict:
value = my_dict["c"]
else:
value = 0
print(value) # 0
  1. Usando o bloco try/except para capturar a exceção e lidar com chaves ausentes:
my_dict = {"a": 1, "b": 2}
try:
value = my_dict["c"]
except KeyError:
value = 0
print(value) # 0

Embora essas abordagens funcionem bem em determinadas situações, elas podem se tornar verbosas e exigir mais código para lidar adequadamente com chaves ausentes. É aqui que o tipo defaultdict entra em jogo.

Entendendo o tipo defaultdict do Python

O tipo defaultdict do Python é uma subclasse de dict que aceita uma função chamada default factory como argumento durante sua inicialização. Essa função é usada para gerar um valor padrão sempre que uma chave ausente é acessada.

Vamos ver um exemplo para entender melhor como o defaultdict funciona. Digamos que queremos contar a ocorrência de cada letra em uma string e armazenar os resultados em um dicionário. Usando um defaultdict, podemos simplificar nosso código da seguinte forma:

from collections import defaultdict
my_string = "banana"
letter_counts = defaultdict(int)
for letter in my_string:
letter_counts[letter] += 1
print(letter_counts) # defaultdict(<class 'int'>, {'b': 1, 'a': 3, 'n': 2})

No exemplo acima, importamos defaultdict do módulo collections e criamos um objeto letter_counts do tipo defaultdict(int), que utiliza o tipo int como função de fábrica padrão. Em seguida, iteramos sobre cada letra da string “banana” e incrementamos a contagem de ocorrência de cada letra. Como o defaultdict gera automaticamente o valor padrão 0 para cada chave ausente, não precisamos nos preocupar em verificar se a chave existe ou definir um valor padrão manualmente. No final, imprimimos o dicionário letter_counts e obtemos o resultado desejado.

Usando o tipo defaultdict do Python

O tipo defaultdict é especialmente útil quando precisamos realizar operações de agrupamento, contagem ou acumulação de valores. Aqui estão alguns exemplos de como usar o defaultdict para essas operações:

Agrupando itens

Suponha que você tenha uma lista de nomes e deseje agrupá-los por suas primeiras letras:

from collections import defaultdict
names = ["Alice", "Bob", "Charlie", "Eve", "Frank"]
grouped_names = defaultdict(list)
for name in names:
grouped_names[name[0]].append(name)
print(grouped_names)
# defaultdict(<class 'list'>, {'A': ['Alice'], 'B': ['Bob'], 'C': ['Charlie'], 'E': ['Eve'], 'F': ['Frank']})

Nesse exemplo, criamos um defaultdict chamado grouped_names com a função de fábrica list. Em seguida, percorremos cada nome na lista de nomes e adicionamos o nome à lista correspondente à sua primeira letra. Dessa forma, obtemos um dicionário em que as chaves são as primeiras letras e os valores são listas de nomes que começam com essa letra.

Agrupando itens únicos

Se quisermos agrupar apenas os nomes únicos por suas primeiras letras, podemos usar um defaultdict com uma função de fábrica set:

from collections import defaultdict
names = ["Alice", "Bob", "Charlie", "Eve", "Frank"]
unique_grouped_names = defaultdict(set)
for name in names:
unique_grouped_names[name[0]].add(name)
print(unique_grouped_names)
# defaultdict(<class 'set'>, {'A': {'Alice'}, 'B': {'Bob'}, 'C': {'Charlie'}, 'E': {'Eve'}, 'F': {'Frank'}})

Neste caso, criamos um defaultdict chamado unique_grouped_names com a função de fábrica set. Isso nos permite armazenar apenas nomes únicos para cada chave. Quando usamos o método add() em um conjunto, ele automaticamente descarta duplicatas.

Contando itens

Para contar a ocorrência de itens em uma lista, podemos usar um defaultdict com uma função de fábrica int e incrementar o valor para cada item encontrado:

from collections import defaultdict
fruits = ["apple", "banana", "apple", "orange", "banana", "banana"]
fruit_counts = defaultdict(int)
for fruit in fruits:
fruit_counts[fruit] += 1
print(fruit_counts)
# defaultdict(<class 'int'>, {'apple': 2, 'banana': 3, 'orange': 1})

Aqui, criamos um defaultdict chamado fruit_counts com a função de fábrica int, que gera o valor padrão 0. Em seguida, percorremos cada fruta na lista fruits e incrementamos o valor correspondente no dicionário fruit_counts. Desta forma, obtemos um dicionário em que as chaves são as frutas e os valores são a contagem de ocorrências de cada fruta.

Acumulando valores

Se precisarmos acumular valores em uma lista para cada chave de um dicionário, podemos usar um defaultdict com uma função de fábrica list:

from collections import defaultdict
fruit_prices = {
"apple": 0.5,
"banana": 0.25,
"orange": 0.75
}
shopping_list = ["apple", "banana", "apple", "orange", "banana", "banana"]
item_prices = defaultdict(list)
for item in shopping_list:
item_prices[item].append(fruit_prices[item])
print(item_prices)
# defaultdict(<class 'list'>, {'apple': [0.5, 0.5], 'banana': [0.25, 0.25, 0.25], 'orange': [0.75]})

Neste exemplo, temos um dicionário fruit_prices com os preços das frutas. Criamos um defaultdict chamado item_prices com a função de fábrica list, que nos permite acumular valores em uma lista. Em seguida, percorremos cada item na lista shopping_list e adicionamos o preço correspondente à lista de preços do item no dicionário item_prices. Dessa forma, obtemos um dicionário em que as chaves são os itens comprados e os valores são as listas de preços correspondentes.

Conclusão

O tipo defaultdict do Python é uma ferramenta poderosa para lidar com chaves ausentes em dicionários. Ele simplifica o código, evita exceções KeyError e permite realizar operações de agrupamento, contagem e acumulação de valores de maneira mais eficiente. Ao entender como usar o defaultdict e explorar suas capacidades, você poderá aproveitar ao máximo esse recurso em suas tarefas de programação.

Lembre-se de que este tutorial pressupõe que você já tenha algum conhecimento prévio sobre dicionários em Python. Se você precisa revisar ou aprender mais sobre o assunto, os recursos mencionados ao longo do texto podem ser úteis para você.

Gostou deste tutorial? Compartilhe nas redes sociais e ajude outros desenvolvedores a dominarem o uso do tipo defaultdict do Python!