A Função `dict` e a Criação de Novos Dicionários em Python
- #Python
Em Python, às vezes é necessário mapear alguns dados simples em estruturas flexíveis, poderosas e organizadas que são chamadas de dicionários. Entretanto, muitas das vezes, esses dados estão espalhados pelo código em várias configurações diferentes como listas, números ou até mesmo objetos. A função dict() nos ajuda a organizar essas configurações em apenas um lugar.
❓ Mas o que são dicionários?
São objetos definidos por uma classe em Python, baseados na estrutura de dados chamada de Tabela Hash, na qual um valor é associado a uma chave. Por exemplo, podemos associar uma chave nome (uma string) a uma valor de idade (um inteiro). Veja o dicionário abaixo e confira um pouco sua sintaxe.
# Sintaxe
dicionario = {
"chave": "valor"
}
# No nosso exemplo acima
nosso_exemplo = {
"Marcos": 21 # "nome": idade
}
Veja que as chaves podem ser de tipos de dados diferentes, como strings ou outros objetos, diferente das listas, as quais só admitem números inteiros. Mas nem tudo pode ser uma chave! Objetos mutáveis, como as listas, não podem ser usados assim. Ademais, a não ser que seja extremamente necessário, evite usar objetos complexos como chaves. Isso garante que suas estruturas estejam simples e coesas. Nesse contexto, vamos implementar um dicionário que associa nomes de usuários (chaves) a idades (valores).
Vale lembrar: Dicionários são estruturas ordenadas (a partir do Python 3.7)
nomes_e_idades = {
"João": 24,
"Maria": 22,
"Débora": 50
}
# Para acessar a idade de João:
# nomes_e_idades[chave] -> Retorna o valor associado
idade_joao = nomes_e_idades["João"]
Com o dicionário definido acima, podemos acessar a idade de qualquer pessoa a partir do seu nome. Veja como é muito mais prático descobrir a idade de João. Só precisamos usar esta sintaxe:
nome = "João"
print(f"A idade de {nome} é {nomes_e_idades[nome]}")
""" Saída
A idade de João é 24
"""
Se usássemos uma lista para esta estrutura, precisaríamos associar um nome a um valor inteiro (índice) da lista. No código abaixo, verifique a dificuldade gerada pelo uso de listas nesse contexto.
idades = [24, 22, 50] # Como saber qual a idade de João?
No código acima, precisaríamos de outras variáveis indicando onde está a idade de cada pessoa (por exemplo, joao_indice = 0). Essa forma não é simples de usar, por isso, usamos os dicionários. Contudo, em alguns momentos precisamos criar novos dicionários em tempo de execução, isto é, enquanto o usuário usa o programa. Por isso, não podemos definir os dicionários explicitamente, como no caso anterior de nomes_e_idades, precisamos usar a função dict()!
🧱 Classes e Construtores
Antes de entrarmos na funcionalidade de dict(), precisamos entender o que são classes e construtores. Classes são definições de objetos que contêm várias funções especiais associadas. Os dicionários nada mais são do que uma classe! Para entender melhor como as classes funcionam, vou dar um exemplo.
class Pessoa: # Definimos a classe que representa uma Pessoa
def __init__(self, nome): # Definimos um construtor (self sempre tem que ser o primeiro argumento)
self.nome = nome # Definimos que esta pessoa guarda um nome consigo
Na classe acima, definimos uma Pessoa! Ela guarda um nome dentro de si (é isso que o self.nome indica). Além disso, criamos uma função especial __init__(), nomeada de construtor! Um construtor é executado sempre que um novo objeto da classe for gerado. Não se preocupe com a sintaxe da classe, apenas entenda como criamos uma nova Pessoa no exemplo abaixo.
nova_pessoa = Pessoa("Pedro") # Criando um objeto com nome Pedro
outra_pessoa = Pessoa("Natália") # Criando outro objeto com nome Natália
print(nova_pessoa.nome) # Imprima o nome contido dentro de nova_pessoa
print(outra_pessoa.nome) # Imprima o nome contido dentro de outra_pessoa
""" Saída
Pedro
Natália
"""
O construtor criará um novo objeto do tipo Pessoa para nós, é isso que a função (construtor) __init__() realiza. Com isso em mente, vamos entender a definição da função dict() (se precisar de ajuda com classes, dê uma olhada aqui ou aqui).
🖋️ A definição da função dict()
De acordo com a documentação do Python, a definição de dict() é disposta abaixo. Para mais informações sobre o termo **kwargs, verifique este artigo.
class dict(**kwargs)
class dict(mapping, **kwargs)
class dict(iterable, **kwargs)
Veja acima que a definição de dict() não é composta por uma função, mas por uma classe. Como dito anteriormente, de modo bastante resumido, dicionários são objetos, os quais, por sua vez, são definidos por classes. Por isso, precisamos chamar uma função especial da classe para criar um novo objeto, o construtor. No exemplo dos dicionários, a função dict() é um construtor que gera um novo dicionário para o programador.
Assim, chamamos o construtor (função) dict() para construir e retornar um novo dicionário para a gente!
Como usar essa função?
Existem três maneiras de se usar a função dict() no Python.
1. Criar um novo dicionário por meio de argumentos
Sabemos que essa função retorna um novo dicionário para nós, mas vamos ver na prática como fazer isso. Existem várias maneiras de se usar essa função. A primeira, mais simples, porém limitada, é passar para ela vários argumentos (é isso que o **kwargs na definição nos indica).
nomes_e_idades = dict(joao=24, maria=22, debora=50) # Passando vários pares chave=valor
print(nomes_e_idades) # Imprime o nosso novo dicionário
print(type(nomes_e_idades)) # Nos retorna o tipo da variável
"""Saída
{'joao': 24, 'maria': 22, 'debora': 50}
<class 'dict'>
"""
Note que um novo dicionário foi gerado. Podemos checar seu tipo na terceira linha de código, com a ajuda da função type().
2. Criar uma cópia de outro dicionário
Podemos também gerar uma cópia de outro dicionário já existente. Podemos fazer isso ao passar o dicionário que queremos copiar para função como um argumento. Veja seu uso abaixo.
nomes_e_idades = {
"João": 24,
"Maria": 22,
"Débora": 50
}
# Preciso de uma cópia!
minha_copia = dict(nomes_e_idades)
Para testar que, de fato, é uma cópia do dicionário, vamos executar o seguinte código. Para mais informações sobre a palavra-chave del, verifique este artigo.
nomes_e_idades = {
"João": 24,
"Maria": 22,
"Débora": 50
}
minha_copia = dict(nomes_e_idades)
del(minha_copia["João"]) # Deleta "João" de "minha_copia"
print(nomes_e_idades == minha_copia) # Os dicionários são iguais?
print(nomes_e_idades) # Aqui, "João" ainda existe!
print(minha_copia) # Aqui, ele foi deletado!
"""Saída
False
{'João': 24, 'Maria': 22, 'Débora': 50}
{'Maria': 22, 'Débora': 50}
"""
Tome muito cuidado com cópias em Python, porque esse artifício pode gerar algumas confusões. Confira este artigo que explica esse ponto de forma mais detalhada. Nesse caso, a cópia é legítima, pois estamos usando o construtor (lembra dele?) para gerar um novo dicionário para nosso uso.
3. Criar um dicionário com lista de tuplas
Outro jeito de usar essa função é passar os pares chave e valor para a função como uma lista de tuplas. Um nome complicado, mas bem simples de entender. Veja uma lista de tuplas no código abaixo (se tuplas é um termo estranho para você, dê uma olhada aqui).
lista_com_tuplas = [("João", 24), ("Maria", 22), ("Débora", 50)]
# ⬇️ Podemos escrever assim se ficar grande demais
outra_lista_com_tuplas = [
("Jonas", 17),
("Marcos", 37),
("Marcelo", 100)
]
Bem, agora é só passar isso para a função dict() e temos nosso novo dicionário.
lista_com_tuplas = [("João", 24), ("Maria", 22), ("Débora", 50)]
meu_dicionario = dict(lista_com_tuplas)
print(meu_dicionario)
"""Saída
{'João': 24, 'Maria': 22, 'Débora': 50}
"""
Em outros casos, pode ocorrer de termos duas listas separadas e querermos juntá-las em um só dicionário. Para fazer isso, podemos usar uma outra função chamada zip, a qual "intercala" as listas e gera várias tuplas com seus itens. Veja como podemos usá-la no contexto do código anterior.
pessoas = ["João", "Maria", "Débora"] # Chaves
idades = [24, 22, 50] # Valores
pessoas_e_idades = dict( zip(pessoas, idades) )
print(pessoas_e_idades)
"""Saída
{'João': 24, 'Maria': 22, 'Débora': 50}
"""
A ordem é importante. Veja o dicionário resultante se usássemos zip(idades, pessoas), ao invés de zip(pessoas, idades).
pessoas = ["João", "Maria", "Débora"] # Chaves
idades = [24, 22, 50] # Valores
pessoas_e_idades = dict( zip(idades, pessoas) )
print(pessoas_e_idades)
"""Saída
{24: 'João', 22: 'Maria', 50: 'Débora'}
"""
🔎 Exemplo Prático - Cálculo de Lucros Mensais
Seu chefe, um magnata do ramo de automóveis, te pediu para calcular os lucros mensais de várias empresas de carro. Ele quer um dicionário com o lucro médio mensal de todas as empresas, pois está pensando em comprar algumas delas. Estas são as empresas e seus respectivos lucros mensais do ano passado.
|-------------- |---------------------------------------------------------------------------|
| Empresa | Lucro Médio por Mês (em bilhões) |
|-------------- |---------------------------------------------------------------------------|
| Ford | [8.91, 1.57, 5.56, 8.3, 6.81, 1.24, 2.64, 6.67, 2.51, 7.89, 1.03, 5.3] |
| Chevrolet | [5.27, 7.0, 6.87, 6.5, 8.5, 5.14, 1.69, 9.84, 8.79, 9.08, 7.99, 3.05] |
| Honda | [5.77, 3.73, 8.68, 7.56, 4.28, 4.36, 5.21, 9.89, 4.15, 2.69, 6.83, 8.61] |
|-------------- |---------------------------------------------------------------------------|
Utilize o que você aprendeu e encontre a resposta! Um código de solução estará abaixo.
✔️ Resposta
À princípio, vamos criar um dicionário baseado nessas empresas.
empresas_e_lucros_mensais = {
"Ford": [8.91, 1.57, 5.56, 8.3, 6.81, 1.24, 2.64, 6.67, 2.51, 7.89, 1.03, 5.3],
"Chevrolet": [5.27, 7.0, 6.87, 6.5, 8.5, 5.14, 1.69, 9.84, 8.79, 9.08, 7.99, 3.05],
"Honda": [5.77, 3.73, 8.68, 7.56, 4.28, 4.36, 5.21, 9.89, 4.15, 2.69, 6.83, 8.61]
}
Entretanto, em muitos casos existem dados demais. É fácil fazer isso para três empresas, mas e se fossem mil? Por isso, vamos usar duas listas: uma contendo o nome das empresas e outra com seus lucros (imagine que extraímos essas listas de algum arquivo de dados).
empresas = ["Ford", "Chevrolet", "Honda"]
lucros_mensais = [
[8.91, 1.57, 5.56, 8.3, 6.81, 1.24, 2.64, 6.67, 2.51, 7.89, 1.03, 5.3],
[5.27, 7.0, 6.87, 6.5, 8.5, 5.14, 1.69, 9.84, 8.79, 9.08, 7.99, 3.05],
[5.77, 3.73, 8.68, 7.56, 4.28, 4.36, 5.21, 9.89, 4.15, 2.69, 6.83, 8.61]
]
empresas_e_lucros_mensais = dict(zip(empresas, lucros_mensais))
Desse modo, criamos um dicionário. Verifique abaixo.
{
'Ford': [8.91, 1.57, 5.56, 8.3, 6.81, 1.24, 2.64, 6.67, 2.51, 7.89, 1.03, 5.3],
'Chevrolet': [5.27, 7.0, 6.87, 6.5, 8.5, 5.14, 1.69, 9.84, 8.79, 9.08, 7.99, 3.05],
'Honda': [5.77, 3.73, 8.68, 7.56, 4.28, 4.36, 5.21, 9.89, 4.15, 2.69, 6.83, 8.61]
}
Mas o trabalho ainda não acabou! Precisamos dos valores de lucro médio mensal do ano inteiro. Nós precisamos iterar (percorrer) o nosso dicionário, realizando os cálculos de média simples. Para isso, vamos usar este trecho de código.
medias = [] # Guarda nossas médias
for empresa in empresas_e_lucros_mensais: # Para cada chave do dicionário
soma = 0
for lucros in empresas_e_lucros_mensais[empresa]: # Iteramos a lista (valores do dicionário)
soma += lucros
medias.append(soma / 12) # Adicionamos a media à lista de médias
empresas_e_medias = dict(zip(empresas, medias)) # Cria nosso dicionário
No código acima, criamos uma lista contendo a média de todas as empresas (verifique este site se você tem alguma dúvida em listas). Por fim, usamos zip() para gerar várias tuplas contendo o nome da empresa e suas médias de lucro mensais. Desse modo, imprimimos o dicionário para nosso chefe.
print(empresas_e_medias)
"""Saída
{'Ford': 4.869166666666667, 'Chevrolet': 6.6433333333333335, 'Honda': 5.9799999999999995}
"""
✨ Conclusão
Neste artigo, você aprendeu sobre dicionários e a função dict(). Os dicionários são estruturas de dados poderosas e rápidas que aderem muito ao seu código, pois trazem organização e simplicidade para as suas estruturas. Além disso, trazem benefícios para qualquer programador que use sua biblioteca, já que é mais versátil de se usar. No entanto, embora sejam úteis, eles não devem substituir uma classe quando esta é necessária. Veja que classes possuem mais funcionalidades e se adequam melhor a outros tipos de abstração. Dito isso, dicionários são pacotes de dados diversos, enquanto classes têm múltiplas funcionalidades que fogem do escopo deste artigo. Com a função dict(), é possível criar várias dessas estruturas de modo facilitado e direto em tempo de execução, o que nos permite mais flexibilidade de estruturação do código, neste contexto, ela é considerada muito útil pelos programadores.
📚 Leituras Adicionais e Referências
Se você ficou com alguma dúvida em algum ponto do artigo, dê uma olhada nesses outros materiais. Para aprofundar mais o conhecimento, dou a dica de sempre ler a documentação oficial do Python.
- Dicionários: https://docs.python.org/3/tutorial/datastructures.html#dictionaries
- Listas: https://pythonacademy.com.br/blog/listas-no-python
- Média Aritmética: https://www.todamateria.com.br/media/
- A Função zip: https://docs.python.org/3/library/functions.html#zip
- Tutorial da Função zip: http://www.bosontreinamentos.com.br/programacao-em-python/como-usar-a-funcao-zip-em-python/
- Palavra-chave del: https://docs.python.org/3/reference/simple_stmts.html#del
- Mais sobre tabelas hash: https://wagnergaspar.com/o-que-e-e-como-funciona-a-estrutura-de-dados-tabela-hash/
- Classes em Python: https://docs.python.org/3/tutorial/classes.html
- Tutorial de Classes: https://www.covildodev.com.br/artigo/classes-python
- Fstrings: https://pythonacademy.com.br/blog/f-strings-no-python
- **kwargs em Python: https://pt.stackoverflow.com/questions/70886/o-que-significa-kwargs-no-python