Dicionários#

Um dicionário em Python é uma estrutura de dados que armazena pares de chave-valor. É a primeira estrutura não ordenada que vamos aprender.

Cada chave deve ser única e imutável (por exemplo, uma string, um número ou uma tupla), enquanto os valores podem ser de qualquer tipo, incluindo listas, listas e até mesmo outros dicionários.

Os dicionários são úteis para armazenar dados que precisam ser rapidamente acessíveis por uma chave descritiva.

Aqui você encontra a documentação oficial de dicionários, cobrindo todos as operações que vamos falar neste capítulo.

Sintaxe básica#

Um dicionário é definido usando chaves {} e cada par de chave-valor é separado por dois pontos :. Os pares são separados por vírgulas ,.

pessoa = {"nome": "João", "idade": 30, "cidade": "São Paulo"}
print(pessoa)
{'nome': 'João', 'idade': 30, 'cidade': 'São Paulo'}

Operações básicas com dicionários#

Acessando valores a partir da chave#

Lembra que com listas e tuplas podemos acessar os elementos pela índice? Pois bem, em dicionário é como se nós atribuíssemos nomes aos índices. Os índices passam a ser as nossas chaves. E ao acessarmos a chave de um dicionário o valor é retornado.

pessoa = {"nome": "João", "idade": 30, "cidade": "São Paulo"}
print(pessoa["nome"])
João

Note que não existe mais o acesso por índices ou posições, como era em listas e tuplas. Por este motivo, os dicionários são estruturas não ordenadas. Não há uma ordem (primeiro, segundo, terceiro) para acessarmos os valores. Vejamos o que acontece caso busquemos pelo primeiro par de chaves e valores através de índices:

pessoa = {"nome": "João", "idade": 30, "cidade": "São Paulo"}
print(pessoa[0])
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Cell In[3], line 2
      1 pessoa = {"nome": "João", "idade": 30, "cidade": "São Paulo"}
----> 2 print(pessoa[0])

KeyError: 0

Esse erro KeyError: 0 ocorre porque o código tentou acessar a chave 0 no dicionário, mas essa chave não existe. As únicas chaves presentes no dicionário são nome, idade e cidade. Em resumo, o erro significa que a chave 0 não foi encontrada.

Modificando o dicionário#

Dicionários são mutáveis assim como listas. Ou seja, uma vez criado, eu consigo modificar seus valores, bem como acrescentar ou remover outros pares de chave e valor.

Se buscarmos por uma chave, por exemplo, profissao, no dicionário pessoa criado acima através da notação pessoa["profissao"] vamos receber a mensagem de erro KeyError: 'profissão', conforme já vimos. Porém, podemos atribuir um valor a esta chave inexistente, e ela será criada.

# pessoa não possui a chave profissão
pessoa = {"nome": "João", "idade": 30, "cidade": "São Paulo"}

# Aqui não estamos acessando a chave profissão, mas sim criando-a!
pessoa["profissao"] = "desenvolvedor"

print(pessoa)
{'nome': 'João', 'idade': 30, 'cidade': 'São Paulo', 'profissao': 'desenvolvedor'}

Nota (acessar vs atribuir)

Lembre-se que acessar é diferente de atribuir. Para acessar, a chave precisa existir. Na atribuição, se a chave não existir, ela será criada.

Caso uma atribuição seja feita a uma chave existente, o valor dela será substituído.

pessoa = {"nome": "João", "idade": 30, "cidade": "São Paulo"}

# O valor correspondente à chave "nome" é substituid por "José"
pessoa["nome"] = "José"

print(pessoa)
{'nome': 'José', 'idade': 30, 'cidade': 'São Paulo'}

É possível remover pares de chave-valor de um dicionário de duas formas: usando o método pop de dicionários ou usando a instrução del. Vejamos:

Usando a instrução del, o par é simplesmente apagado não sendo possível salvá-lo em variáveis.

pessoa = {"nome": "João", "idade": 30, "cidade": "São Paulo"}

# O par de chave-valor correspondente à chave nome deixou de existir
del pessoa["nome"]

print(pessoa)
{'idade': 30, 'cidade': 'São Paulo'}

Já com o método pop, o par de chave-valor é removido, e o valor é salvo na variável definida.

pessoa = {"nome": "João", "idade": 30, "cidade": "São Paulo"}

# O par de chave-valor correspondente à chave nome deixou de existir
idade = pessoa.pop("idade")

print(idade)
print(pessoa)
30
{'nome': 'João', 'cidade': 'São Paulo'}

Métodos comuns de dicionários#

get#

O método get é uma outra forma de acessar uma determinada chave de um dicionário. Ele retorna o valor associado à chave especificada. Porém, diferente do acesso dict['chave'] como vimos acima, se a chave não existir, retorna None ou um valor padrão definido. Vamos ver este método com o mesmo exemplo acima:

# pessoa não possui a chave profissão
pessoa = {"nome": "João", "idade": 30, "cidade": "São Paulo"}

# Acessando uma chave inexistente com o método get()
print(pessoa.get("profissao"))

# Caso a chave não exista, podemos passar um valor padrão que será retornado
print(pessoa.get("profissao", "desenvolvedor"))
None
desenvolvedor

O grande diferencial ao usar o método get é que nunca teremos o erro KeyError no caso de acessar uma chave inexistente. Eu, particularmente, considero até uma forma mais segura de acessar chaves de um dicionário através deste método.

keys, values e items#

Estes 3 métodos são basicamente para listar as chaves (keys), valores (values) e pares de chave-valor (items) de um dicionário.

pessoa = {"nome": "João", "idade": 30, "cidade": "São Paulo"}

# Aqui serão impressas somente as chaves do dicionário
print(pessoa.keys())

# Aqui serão impressas somente os valores do dicionário
print(pessoa.values())

# E finalmente a combinação dos pares de chave-valor
print(pessoa.items())
dict_keys(['nome', 'idade', 'cidade'])
dict_values(['João', 30, 'São Paulo'])
dict_items([('nome', 'João'), ('idade', 30), ('cidade', 'São Paulo')])

O último método items em especial é bem interessante. Ele retorna algo similar à uma lista de tuplas, e cada tupla contém 2 elementos, a chave e o seu respectivo valor. Vamos retornar à este método quando formos aprender sobre laços de repetição for.

Outras operações com dicionários#

Podemos medir a quantidade de pares chave-valor através da função len.

pessoa = {"nome": "João", "idade": 30, "cidade": "São Paulo"}

print(len(pessoa))
3

É possível trabalhar com junções e atualizações de vários dicionários usando os operadores | e |=.

Nota (operadores de junção/atualização)

Ambos os operadores | e |= só estão disponíveis nas versões do Python 3.9+. Caso estes operadores sejam usados em códigos Python executados na versão 3.8 ou anterior, o código apresentará um erro!

O operador | une os pares de chave e valor de dois dicionários, criando um terceiro dicionário.

informacoes_basicas_produto = {"nome": "Cadeira", "preco": 150, "codigo": "abc"}

informacoes_adicionais_produto = {"cor": "azul", "estoque": 20, "codigo": "xyz"}

informacoes_produto = informacoes_basicas_produto | informacoes_adicionais_produto

print(informacoes_produto)
{'nome': 'Cadeira', 'preco': 150, 'codigo': 'xyz', 'cor': 'azul', 'estoque': 20}

Se dois dicionários têm a mesma chave e você os une com a | b, o valor da chave no dicionário final será o do dicionário b, que está à direita na união. Ou seja, os valores do dicionário b prevalecem sobre os do dicionário a quando há chaves iguais. Foi o que aconteceu com a chave codigo no exemplo acima.

Já o operador |= é usado para atualizar um dicionário existente, combinando-o com outro dicionário.

cliente = {"nome": "Maria", "idade": 28, "possui_conveio": True}

novas_informacoes = {
    "email": "maria@example.com",
    "idade": 29,
    "possui_convenio": False,
}

cliente |= novas_informacoes

print(cliente)
{'nome': 'Maria', 'idade': 29, 'possui_conveio': True, 'email': 'maria@example.com', 'possui_convenio': False}

A diferença entre | e |= está na maneira como eles combinam dicionários.

O operador | cria um novo dicionário resultante da combinação de dois dicionários, sem modificar os originais. No exemplo acima, os dicionários informacoes_basicas_produto e informacoes_adicionais_produto mantiveram-se inalterados.

Já o operador |= atualiza diretamente o dicionário à esquerda com os pares chave-valor do dicionário à direita, modificando-o. O dicionário cliente no exemplo foi alterado.

Portanto, podemos afirmar que | é uma operação imutável, e |= é mutável.

Prática#

Vamos colocar a mão na massa? O exercício 10 é um mega exercício super completo que usa um contexto real de negócios!

Conclusão#

Neste capítulo, exploramos os dicionários, uma estrutura de dados não ordenada fundamental em Python que permite mapear chaves a valores de forma eficiente. Aprendemos como criar, acessar, modificar e remover elementos, além de métodos úteis como get, keys, values e items. Na sequência, vamos aprender sobre a última estrutura de dados básicas de Python: os conjuntos.