Como usar o defaultdict do Python de forma fácil?
Usando o tipo defaultdict do Python para lidar com chaves ausentes
Uma problema comum que pode surgir ao trabalhar com dicionários em Python é tentar acessar ou modificar chaves que não existem no dicionário. Isso resultará em um KeyError
e interromperá a execução do código. Para lidar com esse tipo de situação, a biblioteca padrão do Python fornece o tipo defaultdict
, uma classe semelhante a um dicionário que está disponível em collections
.
O tipo defaultdict
do Python se comporta quase exatamente como um dicionário Python comum, mas se você tentar acessar ou modificar uma chave ausente, o defaultdict
criará automaticamente 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. - Como usar um
defaultdict
para agrupar , contar e acumular valores.
Com esse conhecimento, você estará em melhores condições para usar efetivamente o tipo defaultdict
do Python em seus desafios de programação diários.
Para aproveitar ao máximo este tutorial, é necessário ter algum conhecimento prévio sobre o que são dicionários em Python e como trabalhar com eles. Se você precisar refrescar a memória, consulte os seguintes recursos:
Bônus gratuito: Clique aqui para obter um Python Cheat Sheet e aprender o básico do Python 3, como trabalhar com tipos de dados, dicionários, listas e funções Python.
Lidando com chaves ausentes em dicionários
- Usando try…except:
- Usando o método
get()
:
- Usando o módulo
collections.defaultdict
:
- Definindo um valor padrão antes de acessar o dicionário:
Embora todas essas abordagens possam funcionar, o uso do tipo defaultdict
do Python oferece uma alternativa mais elegante e eficiente para lidar com chaves ausentes em dicionários. Vamos explorar mais sobre o defaultdict
e como usá-lo de maneira eficaz.
Entendendo o tipo defaultdict
do Python
O tipo defaultdict
do Python, que está disponível no módulo collections
, é uma subclasse do tipo dict
padrão do Python. Ao contrário de um dicionário comum, o defaultdict
requer um argumento no momento da criação, chamado de default_factory
. Esse argumento pode ser uma função ou uma classe que será chamada para gerar um valor padrão sempre que uma chave ausente for acessada.
Internamente, o defaultdict
armazena a função default_factory
em um atributo chamado do defaultdict.default_factory
, que é uma função chamada sempre que uma chave ausente é solicitada. Essa função pode retornar qualquer valor e será usada para criar a chave ausente no defaultdict
.
O exemplo a seguir mostra como criar um defaultdict
com uma função default_factory
que retorna uma string vazia sempre que uma chave ausente é acessada:
Nesse exemplo, my_dict["key"]
retorna uma string vazia ""
em vez de lançar um KeyError
, porque a função str
é a função default_factory
definida para o defaultdict
. No momento em que a chave “key” é acessada e não é encontrada, a função str
é chamada, e seu valor de retorno é usado como o valor padrão para a chave “key” no defaultdict
.
É importante ressaltar que a função default_factory
é chamada apenas para as chaves ausentes que não podem ser encontradas no defaultdict
. Se uma chave existente for acessada, o defaultdict
se comportará como um dicionário normal, retornando o valor correspondente à chave.
Usando o tipo defaultdict
do Python
Agora que você entende como o tipo defaultdict
do Python funciona, vamos explorar algumas maneiras de usá-lo para lidar com chaves ausentes em dicionários.
Agrupando itens
Suponha que você tenha uma lista contendo vários itens e queira agrupar esses itens por uma determinada propriedade. Usando um defaultdict
, você pode simplificar esse processo de agrupamento. Por exemplo, vamos agrupar uma lista de nomes por sua primeira letra:
A saída do código acima será um defaultdict
que agrupa os nomes por sua primeira letra:
Observe que a função default_factory
definida para o defaultdict
é list
, o que faz com que cada chave ausente seja automaticamente associada a uma lista vazia. Assim, quando o loop for percorrido e um nome for processado, a primeira letra do nome será usada como chave para acessar um item de lista no defaultdict
. Se a chave não existir, uma lista vazia será criada automaticamente e o nome será adicionado a essa lista. Dessa forma, todos os nomes com a mesma primeira letra serão agrupados corretamente no defaultdict
.
Agrupamento de itens únicos
Além de agrupar todos os itens, você também pode agrupar apenas os itens únicos em um defaultdict
.
Nesse exemplo, a função default_factory
é set
. Isso permite que cada chave ausente seja automaticamente associada a um set
vazio. Durante o loop, cada nome é adicionado ao conjunto associado à chave correspondente à primeira letra do nome. Como um conjunto não permite itens repetidos, apenas os nomes únicos serão mantidos no defaultdict
ao final do loop.
Contagem de itens
Outra tarefa comum ao lidar com dicionários é contar a ocorrência de determinados itens. O tipo defaultdict
pode simplificar essa tarefa, fornecendo uma contagem automática para itens ausentes.
Nesse exemplo, a função default_factory
é int
, que define um padrão de valor como 0
. Ao acessar uma chave ausente, será retornada automaticamente a contagem zero. No loop, ao encontrar um item de fruta, a contagem da fruta correspondente é incrementada em 1
. Ao final do loop, o defaultdict
conterá a contagem de ocorrências de cada fruta.
Acumulando valores
O tipo defaultdict
também pode ser útil ao acumular valores em um dicionário.
Nesse exemplo, a função default_factory
é float
, que define um padrão de valor como 0.0
. No loop, a cada transação, o valor do montante é acumulado na chave correspondente ao ID do cliente no defaultdict
. Dessa forma, ao final do loop, o defaultdict
conterá o total acumulado de cada cliente.
Explorando mais sobre defaultdict
Além das operações básicas discutidas até agora, vamos explorar mais algumas funcionalidades do defaultdict
.
defaultdict
vs dict
Uma das principais diferenças entre um defaultdict
e um dicionário comum é que o defaultdict
não lança um KeyError
ao tentar acessar uma chave ausente. Em vez disso, ele cria a chave ausente e associa automaticamente um valor padrão a ela usando a função default_factory
. Por outro lado, um dicionário normal lançará um KeyError
ao tentar acessar uma chave que não existe.
defaultdict.default_factory
Você pode acessar e modificar a função default_factory
de um defaultdict
por meio do atributo default_factory
. Isso permite que você altere o comportamento padrão do defaultdict
a qualquer momento, alterando a função default_factory
para uma nova função ou classe.
Nesse exemplo, my_dict.default_factory
é inicialmente int
, que define um padrão de valor como 0
. Em seguida, modificamos my_dict.default_factory
para float
, alterando assim o padrão de valor para 0.0
. Isso significa que, se uma chave ausente for acessada no defaultdict
após essa alteração, ela gerará um valor padrão de 0.0
.
defaultdict
vs dict.setdefault()
Uma alternativa para usar um defaultdict
é usar o método setdefault()
de um dicionário comum. A principal diferença é que o defaultdict
oferece uma semântica mais elegante e eficiente. Vamos considerar o seguinte exemplo:
Nesse exemplo, o defaultdict
criará automaticamente as chaves “key1” e “key2” com os valores padrão 0
. No entanto, ao usar o método setdefault()
de um dicionário comum, você precisa especificar um valor padrão explicitamente para cada chave, mesmo que a chave já exista.
É possível obter o mesmo resultado com um dicionário comum, mas a sintaxe é menos intuitiva e pode ser mais suscetível a erros.
defaultdict.__missing__()
O método especial __missing__()
é chamado sempre que uma chave ausente é acessada em um defaultdict
. Por padrão, esse método simplesmente retorna o valor padrão associado à chave pelo default_factory
. No entanto, esse método pode ser substituído para fornecer comportamentos personalizados ao acessar chaves ausentes.
Nesse exemplo, definimos uma classe derivada de defaultdict
chamada MissingKeyDict
que substitui o método __missing__()
. Quando uma chave ausente é acessada, o método __missing__()
é chamado e retorna uma mensagem personalizada indicando que a chave está ausente.
Emulando o tipo defaultdict
do Python
Embora o tipo defaultdict
do Python seja útil para muitas situações, pode haver casos em que você não pode usar o defaultdict
diretamente. No entanto, você ainda pode emular o comportamento do defaultdict
criando suas próprias classes ou funções personalizadas.
Nesse exemplo, definimos uma função default_value()
que retorna o valor padrão desejado e, em seguida, usamos essa função para criar um defaultdict
personalizado por meio da função my_dict()
. Dessa forma, podemos obter o mesmo comportamento de um defaultdict
usando nossa própria implementação.
Passando argumentos para .default_factory
Além de usar funções simples para criar defaultdicts
, você também pode usar funções mais complexas e até mesmo funções que aceitam argumentos. Existem várias maneiras de passar argumentos para a função default_factory
, como usando lambda
ou o módulo functools.partial()
.
Usando lambda
O lambda
é uma função anônima que pode ser usada para criar funções simples em uma única linha. Você pode usar lambda
para criar uma função sob demanda ao criar um defaultdict
.
Nesse exemplo, usamos lambda: "Unknown"
como a função default_factory
. Isso cria uma função anônima que sempre retorna a string "Unknown"
como valor padrão. Portanto, ao acessar uma chave ausente no defaultdict
, o valor padrão será "Unknown"
.
Usando functools.partial()
O módulo functools
fornece a função partial()
que pode ser usada para criar funções personalizadas com argumentos fixos. Dessa forma, você pode criar uma função parcial que será usada como a função default_factory
no defaultdict
.
Nesse exemplo, partial(default_value, default="Unknown")
cria uma função parcial que usa a função default_value
com o argumento fixo default="Unknown"
. Portanto, ao acessar uma chave ausente no defaultdict
, o valor padrão será "Unknown"
.
Conclusão
O tipo defaultdict
do Python é uma ferramenta poderosa para lidar com chaves ausentes em dicionários. Com ele, você pode simplificar tarefas comuns, como agrupamento, contagem e acumulação de valores. Além disso, você pode personalizar o comportamento do defaultdict
para se adequar às suas necessidades específicas.
No entanto, tenha em mente que o defaultdict
pode consumir mais memória do que um dicionário comum, pois armazena explicitamente todas as chaves ausentes e seus valores padrão. Portanto, use-o com sabedoria e considere outras abordagens, dependendo do contexto e dos requisitos do seu projeto.
Com o conhecimento adquirido neste tutorial, você estará pronto para usar o tipo defaultdict
do Python para lidar com chaves ausentes em dicionários e melhorar suas habilidades de programação em Python.