Pular para o conteúdo principal

Dicionários

Conhecidos também como HashMaps ou Arrays Associativos os dicionários são um misto entre o set e list e com certeza a estrutura de dados mais importante da linguagem.

Curiosidade: Todos os tipos de dados do Python são implementados usando dicionários, os objetos possuem um método especial __dict__, experimente no terminal imprimir int.__dict__, até mesmo a resolução de nomes do Python é feita usando um dicionário __builtins__.__dict__ quando digitamos print o Python vai ali naquele dicionário verificar se existe uma função chamada print lá dentro.

Vamos entender para que servem os dicionários com este exemplo usando tipos primários.

produto_nome = "Caneta"
produto_cor1 = "azul"
produto_cor2 = "branco"
produto_preco = 3.23
produto_dimensao_altura = 12.1
produto_dimensao_largura = 0.8
produto_em_estoque = True
produto_codigo = 45678
produto_codebar = None

Acima representamos um único produto num programa de vendas, é uma única caneta, porém precisamos de 9 objetos de diferentes tipos.

E para resolver este problema que temos os tipos compostos, eles são containeres, objetos que podem agrupar mais de um tipo e mais de uma unidade de informação dentro deles.

Dicionários são criados com { } ou através da classe dict(), é bom ter cuidado para não os confundir com sets já que sets também usam { } e a diferença principal é que no set cada posição armazena apenas um valor e nos dicionários podemos colocar 2 valores em cada posição.

Um desses valores é chamado de chave key e o outro valor val e são separados por :, veja com um dicionário a mesma informação pode ser representada com:

produto = {
"nome": "Caneta",
"cor1": "azul",
"cor2": "branco",
"preco": 3.23,
"dimensao_altura": 12.1,
"dimensao_largura": 0.8,
"em_estoque": True,
"codigo": 45678,
"codebar": None,
}

Agora temos um único objeto produto do tipo dict e isso torna o nosso programa muito melhor organizado, facilita operações e deixa a complexidade menor também, pois os dicionários assim como os sets também implementam a Hash Table, ou seja, as operações de acesso são O(1) super-rápidas.

Assim como as listas os dicionários podem receber subscrições a partir de uma chave, ou seja, usamos [] e dentro passamos a key que queremos acessar.

produto["nome"]
'Caneta'
produto["codigo"]
45678

Além disso, podemos diminuir a redundância colocando objetos compostos dentro do dicionário, ao invés de 2 chaves para representar cor podemos criar uma lista de cores e ao invés de 2 chaves para dimensões podemos ter um subdicionário.

produto = {
"nome": "Caneta",
"cores": ["azul", "branco"],
"preco": 3.23,
"dimensao": {
"altura": 12.1,
"largura": 0.8,
},
"em_estoque": True,
"codigo": 45678,
"codebar": None,
}

As chaves de um dicionário podem ser de qualquer tipo de dados que seja compatível com hash table, exemplo:

d = {
10: "Bruno",
True: 45,
False: None,
None: True,
(4,5,6): "uma tupla",
}

>>> d[(4, 5, 6)]
'uma tupla'

Mas não podemos usar tipos unhashable.

d = {[1, 2, 3]: "uma lista"}
...
TypeError: unhashable type: 'list'

Já os valores podem ser de qualquer tipo sem restrições!

Sintaxe

Podemos iniciar um dicionário vazio e depois ir adicionando elementos dentro dele.

cliente = {}
# ou
cliente = dict()

CRUD

E usar as operações de CRUD (Create, Read, Update, Delete)

Criar - Adicionar chave+valor

cliente["nome"] = "Bruno"

Ler valor a partir de uma chave

cliente["nome"]  # Output: 'Bruno'

Update - Alterar valor a partir de uma chave

cliente["nome"] = "Bruno Rocha"

Delete - Remover um valor e sua chave.

del cliente["nome"]

A keyword del remove uma variável que foi atribuída e pode ser usada com chaves de dicionários.

Buscas

O dicionário implementa Hash Table, ele também é conhecido como hash map, portanto, as buscas em dicionário quando feitas por chave tem acesso constante O(1).

"nome" in cliente
True

in invoca o protocolo Lookupable através do método __contains__ e efetua a busca imediata sem necessidade de iterar todo o dicionário para encontrar uma chave, e assim como os sets as chaves não podem se repetir.

Métodos de Lookup

Obter uma lista de chaves

cliente = {"nome": "Bruno", "cidade": "Viana"}

cliente.keys()
dict_keys(["nome", "cidade"])

Obter uma lista de valores

cliente.values()
dict_keys(["Bruno", "Viana"])

Obter uma lista de tuplas contendo chave e valor

cliente.items()
dict_items([("nome", "Bruno"), ("cidade", "Viana")])

Iterando com for

# apenas chaves
for key in cliente:
print(key)

nome
cidade

# Buscando os valores com subscrição

for key in cliente:
print(key, "-->", cliente[key])

nome-->Bruno
cidade-->Viana

# Com desenpacotamento de tuplas

for key, value in cliente.items():
print(key, "-->", value)

nome-->Bruno
cidade-->Viana

Combinando 2 dicionários

# informacao original
cliente = {"nome": "Bruno", "cidade": "Viana"}

# informacao adicional
extra = {"pais": "Portugal"}

# Informação final
final = {**cliente, **extra}
print(final)
{"nome": "Bruno", "cidade": "Viana", "pais": "Portugal"}

Ou fazendo update in place.

# informacao original
cliente = {"nome": "Bruno", "cidade": "Viana"}

# informacao adicional
extra = {"pais": "Portugal"}

# Cliente atualizado
cliente.update(extra)
print(cliente)
{"nome": "Bruno", "cidade": "Viana", "pais": "Portugal"}

Erros

Caso uma chave não exista no dicionário o Python estoura um erro chamado KeyError

print(cliente["telefone"])
...
KeyError 'telefone'

Para evitar o erro podemos usar o método get que busca a chave e caso não exista retorna um valor padrão que inicialmente é None

print(cliente.get("telefone"))
'None'

print(cliente.get("telefone", "191"))
'191'