Python Iluminado

Dicionários

img

Os dicionários são encontrados em outros linguagens de programação como "memórias associativas" ou "matrizes associativas". Ao contrário das seqüências, que são indexadas por um intervalo de números, os dicionários são indexados por chaves, que podem ser de qualquer tipo imutável.

Eles são uma coleção não-ordenada de pares de chave & valor, são normalmente usados quando temos uma grande quantidade de dados.

Dicionários são otimizados para buscarmos dados e para isso, precisamos saber sua chave.

Dicionários são definidos entre chaves {} onde cada item é um par na forma de chave:valor, separados por ,, sendo a chave e o valor podendo ser de qualquer tipo.

Chaves:

  • Devem ser únicas
  • Tipo imutável (int, float, string, tuple, bool) - Na verdade precisa de um objeto que seja hashable, mas imagine como imutável uma vez que todos os tipos imutáveis são hashable - Tenha cuidado com o tipo float como chave
  • Nenhuma ordem para chaves ou valores

Valores:

  • Qualquer tipo (imutável e mutável)
  • Pode ser duplicado
  • Valores de dicionários podem ser listas, até mesmo outros dicionários

Para compreendermos melhor o funcionamento dos dicionários, vamos definir alguns exemplos:

album = {'nome':'A Night at the Opera','artista':'Blind Guardian','lançamento':2002}
print(type(album)) # <class 'dict'>
print(album) # {'nome': 'A Night at the Opera', 'artista': 'Blind Guardian', 'lançamento': 2002}
print(album['nome']) # A Night at the Opera
print(album['artista']) # Blind Guardian
print(album['lançamento']) # 2002

Também podemos definir um dicionário dessa forma, o que torna ele mais legível:

elemento = {
"nome":"Ouro",
"símbolo":"Au",
"número atômico":79
}

Acessando e Manipulando Dados

Para acessarmos os itens do dicionário, precisamos nos referir a sua chave, por exemplo:

print(elemento["nome"]) # Ouro

Podemos também utilizar o método get() para acessarmos:

print(elemento.get("nome")) # Ouro

É possível alterar os valores de um dicionário, podemos fazê-lo da seguinte maneira:

elemento["nome"] = "Prata"
elemento["símbolo"] = "Ag"
elemento["número atômico"] = 47
print(elemento) # {'nome': 'Prata', 'símbolo': 'Ag', 'número atômico': 47}

Imprimindo os Valores de um Dicionário

Podemos usar o for loop para imprimir os elementos de um dicionário.

personagem = {
"nome" : "Gandalf",
"classe" : "Wizard",
"ordem" : "Istari"
}
for key in personagem: # Percorre os valores do dicionário
print(personagem[key]) # Imprime os valores do dicionário

Também podemos usar o método values() da seguinte forma:

for p in personagem.values(): # Percorre os valores do dicionário
print(p) # Imprime os valores do dicionário

Além disso é possível percorrer tanto as chaves como os valores, usando a função items():

for chave,valor in personagem.items(): # Percorre as chaves e os valores
print(f'{chave} : {valor}') # Imprime as chaves e os valores

Caso seja necessário verificar a presença de uma chave no dicionário, podemos fazer o teste com a palavra-chave in:

print('nome' in personagem) # True

Também podemos testar pela presença de um determinado valor no dicionário:

print("Gandalf" in personagem.values()) # True

Assim como nas listas e tuplas, também podemos aplicar o método len() nos dicionários:

print(len(personagem)) # 3

Adicionando Itens ao Dicionário

Para adicionarmos um novo item em nosso dicionário usamos uma nova chave e atribuimos um valor a ela

personagem['altura'] = 1.85
print(personagem) # {'nome': 'Gandalf', 'classe': 'Wizard', 'Ordem': 'Istari', 'altura': 1.85}

Removendo Itens do Dicionário

É possível também, de várias formas, remover os itens de um dicionário.

Usando o método pop(), nos será retornado o item removido:

personagem.pop('altura') # 1.85
print(personagem) # {'nome': 'Gandalf', 'classe': 'Wizard', 'Ordem': 'Istari'}

Usando o método popitem(), remove o último par de chave-valores adicionado de personagem e o retorna como uma tupla:

personagem.popitem() # ('Ordem', 'Istari')
print(personagem) # {'nome': 'Gandalf', 'classe': 'Wizard'}

A palavra-chave del remove um item com a chave especificada:

del personagem['classe']
print(personagem) # {'nome': 'Gandalf'}

Além disso é possível deletar o dicionário por completo com del, tenha muita atenção, pois todos os dados serão perdidos.

del personagem
print(personagem) # NameError: name 'personagem' is not defined

Construtor dict()

Através do construtor dict() também é possível criarmos dicionários:

pessoa = dict(nome="Jesus", idade=33)
print(pessoa) # {'nome': 'Jesus', 'idade': 33}

Uma outra maneira de atualizarmos os dados de um dicionário é com o uso do método update():

pessoa.update({'nome':'Immanuel'})
print(pessoa) # {'nome': 'Immanuel', 'idade': 33}

Método clear()

O método clear() nos permite esvaziar o dicionário por completo:

pessoa.clear()
print(pessoa) # {}

Ordenando um Dicionário

Vamos agora criar um dicionário chamado de pokedex, este será um pequeno registro de alguns pokémons, que iremos ordernar através de expressões lambda.

Criando o Dicionário:

pokedex = [
{'nome':'pikachu','tipo':'elétrico'},
{'nome':'charizard','tipo':'fogo'},
{'nome':'bulbasaur','tipo':'planta'},
{'nome':'squirtle','tipo':'aquatico'}
]

Ordenando os pokémons por tipo através de uma expressão lambda:

ordenados = sorted(pokedex, key=lambda x: x['tipo'])
print(ordenados)
# [{'nome': 'squirtle', 'tipo': 'aquatico'}, {'nome': 'pikachu', 'tipo': 'elétrico'}, {'nome': 'charizard', 'tipo': 'fogo'}, {'nome': 'bulbasaur', 'tipo': 'planta'}]

Dicionários Comprehensions

Supondo que tenhamos por exemplo duas listas e desejamos montar um dicionário através delas, podemos usar a técnica de comprehensions para executar tal tarefa.

Para este exemplo, vamos primeiro iniciar duas listas e com elas, construíremos um dicionário:

autores = ['Aldous Huxley','George Orwell','Ray Bradbury','William Gibson']
livros = ['Brave New World','1984','Fahrenheit 451','Neuromancer']
autores_livros = {autor: livro for autor, livro in zip(autores, livros)}
print(autores_livros)
# {'Aldous Huxley': 'Brave New World', 'George Orwell': '1984', 'Ray Bradbury': 'Fahrenheit 451', 'William Gibson': 'Neuromancer'}

Um dictionary comprehension também pode conter o statement if, que pode ser usado para filtrarmos itens.

Vejamos como podemos formar um dicionário apenas com números pares e seus respectivos quadrados:

quadrados_pares = {x: x*x for x in range(11) if x % 2 == 0}
print(quadrados_pares) # {0: 0, 2: 4, 4: 16, 6: 36, 8: 64, 10: 100}

Dicionários Aninhados

Os dicionários são uma estrutura de dados muito flexível e nos permitem até mesmo guardar dicionários dentro de um dicionário, de forma que possamos acessá-los através de uma chave. Vejamos um exemplo para ilustrar:

jogos = {
'1':{'nome':'castlevania','genero':'aventura'},
'2':{'nome':'super mario','genero':'aventura'},
'3':{'nome':'world of warcraft','genero':'MMORPG'}
}
print(jogos['2']) # {'nome': 'super mario', 'genero': 'aventura'}
print(jogos.get('1')) # {'nome': 'castlevania', 'genero': 'aventura'}
print(jogos['3']['nome']) # world of warcraft

Copiando um Dicionário

Você não pode copiar um dicionário simplesmente digitando copia_filme = filme, porque: copia_filme será apenas uma referência para filme, e as alterações feitas em filme também serão feitas automaticamente em copia_filme.

Uma maneira de copiarmos um dicionário é usando o método interno copy():

filme = {'titulo':'Lord of the Rings','Gênero':'Aventura'}
print(filme) # {'titulo': 'Lord of the Rings', 'Gênero': 'Aventura'}
copia_filme = filme.copy()
print(copia_filme) # {'titulo': 'Lord of the Rings', 'Gênero': 'Aventura'}

Se eventualmente alterarmos o dicionário filme, a cópia não será afetada:

filme['Gênero'] = 'Fantasia'
print(filme) # {'titulo': 'Lord of the Rings', 'Gênero': 'Fantasia'}
print(copia_filme) # {'titulo': 'Lord of the Rings', 'Gênero': 'Aventura'}

Uma outra opção para copiarmos um dicionário é com o uso do método dict(), ao qual já vimos anteriormente.

copia_filme = dict(filme)
print(copia_filme) # {'titulo': 'Lord of the Rings', 'Gênero': 'Fantasia'}
filme['titulo'] = 'The Hobbit: An Unexpected Journey'
print(filme) # {'titulo': 'The Hobbit: An Unexpected Journey', 'Gênero': 'Fantasia'}
print(copia_filme) # {'titulo': 'Lord of the Rings', 'Gênero': 'Fantasia'}

Fibonacci com Dicionários

Podemos utilizar o poder dos dicionários para otimizar uma função Fibonnaci e tornar seus resultados mais rápidos ao guardarmos os valores já computados em um dicionário. Esta técnica é conhecida como Memoization.

def fib_eficiente(n, d):
if n in d:
return d[n]
else:
resposta = fib_eficiente(n-1, d) + fib_eficiente(n-2, d)
d[n] = resposta
return resposta
d = {1:1, 2:2}
print(fib_eficiente(8, d)) # 34

Podemos concluir que os dicionários são uma estrutura de dados que nos oferece uma maneira eficaz de guardar e buscar os dados, considere a importância deles para usos no futuro.