Python Dicionários
Numa lista, você acha um item pela posição: o primeiro, o segundo, o quinto. Mas no balcão da padaria ninguém pergunta "quanto custa o produto número 2?"; pergunta "quanto custa o leite?". Para achar um valor por um nome o Python tem o dicionário (em inglês, dictionary, e no código, dict): cada valor fica guardado junto de uma chave, e é pela chave que você o encontra.
- O que são chave e valor, e como criar um dicionário com
{chave: valor}. - A ler um valor pela chave:
precos["leite"]. - O
KeyError, o erro de pedir uma chave que não existe, e como evitá-lo comget()ein. - Que o dicionário guarda a ordem em que as chaves entraram.
- O que pode ser chave (texto, número, tupla) e o que não pode (lista).
- Os erros reais de maiúscula, de índice, de ponto e de chave sem aspas.
A ideia: o dicionário de verdade
Num dicionário de papel, você procura a palavra e encontra o significado. Ninguém lê o dicionário inteiro até achar "padaria": vai direto à letra P. A palavra é a chave; o significado é o valor.
A tabela de preços pendurada na padaria funciona igual: à esquerda o nome do produto, à direita o preço.
| Chave (o nome) | Valor (o que está guardado) |
|---|---|
"pão" | 0.50 |
"leite" | 4.75 |
"café" | 18.90 |
Cada linha é um par chave-valor. Em Python, essa tabela inteira cabe numa variável.
1. Criando um dicionário
precos = {"pão": 0.50, "leite": 4.75, "café": 18.90}
print(precos)
print(type(precos))
print(len(precos))
- { … }
- As chaves envolvem o dicionário inteiro, como no conjunto. O que faz a diferença é o dois-pontos lá dentro.
- "pão": 0.50
- Um par: a chave
"pão", o dois-pontos:, e o valor0.50. Leia como "pão vale 0.50". - ,
- A vírgula separa um par do outro.
- type(precos)
- O tipo se chama
dict. - len(precos)
- Quantos pares há no dicionário: 3.
$ python3 di_criar.py
{'pão': 0.5, 'leite': 4.75, 'café': 18.9}
<class 'dict'>
3
O Python mostrou 0.5 e 18.9, sem o zero do fim: para ele, 0.50 e 0.5 são o mesmo número. Para mostrar com duas casas, use a f-string com :.2f, como na próxima seção.
Quando há muitos pares, o costume é escrever um por linha, com 4 espaços na frente. A vírgula depois do último é permitida e facilita acrescentar outro depois:
precos = {
"pão": 0.50,
"leite": 4.75,
"café": 18.90,
}
2. Lendo um valor pela chave
Para pegar um valor, escreva o nome do dicionário e a chave entre colchetes, como o índice de uma lista, só que com a chave no lugar do número:
precos = {"pão": 0.50, "leite": 4.75, "café": 18.90}
print(precos["leite"])
print(f"O café custa R$ {precos['café']:.2f}")
total = precos["pão"] * 10 + precos["leite"]
print(f"Total: R$ {total:.2f}")
$ python3 di_acessar.py 4.75 O café custa R$ 18.90 Total: R$ 9.75
- precos["leite"]
- "O valor guardado na chave
"leite"": 4.75. - {precos['café']:.2f}
- Dentro de uma f-string com aspas duplas, a chave vai com aspas simples, para não fechar o texto antes da hora (veja f-strings).
- precos["pão"] * 10 + precos["leite"]
- O valor lido é um número comum: dá para fazer contas. Dez pães e um leite: R$ 9.75.
Missão: troque o 0 pela leitura do preço do café no dicionário, para o programa mostrar Café: R$ 18.90.
precos = {"pão": 0.50, "leite": 4.75, "café": 18.90}
print(f"Café: R$ {0:.2f}")
precos = {"pão": 0.50, "leite": 4.75, "café": 18.90}
print(f"Café: R$ {precos['café']:.2f}")
3. A chave que não existe: KeyError
A padaria não vende bolo. O que acontece se o programa pedir o preço do bolo?
precos = {"pão": 0.50, "leite": 4.75, "café": 18.90}
print(precos["bolo"])
$ python3 di_keyerror.py
Traceback (most recent call last):
File "/home/ana/di_keyerror.py", line 2, in <module>
print(precos["bolo"])
~~~~~~^^^^^^^^
KeyError: 'bolo'
- Traceback (most recent call last):
- Deu erro; abaixo vem onde.
- File "/home/ana/di_keyerror.py", line 2
- Na linha 2 do programa.
- ~~~~~~^^^^^^^^
- Os
^apontam para["bolo"]: a chave pedida. - KeyError: 'bolo'
- "Erro de chave": a chave
'bolo'não existe no dicionário. A mensagem é só o nome da chave que faltou, e é a pista para você saber qual foi.
Com colchetes, o dicionário é rigoroso: chave que não existe é erro, e o programa para. Há duas formas de perguntar com cuidado.
Forma 1: get(), que não dá erro
precos = {"pão": 0.50, "leite": 4.75, "café": 18.90}
print(precos.get("leite"))
print(precos.get("bolo"))
print(precos.get("bolo", 0))
print(precos.get("bolo", "não temos"))
$ python3 di_get.py 4.75 None 0 não temos
- precos.get("leite")
- "Pegar": com a chave existindo, é igual a
precos["leite"]. - precos.get("bolo")
- Com a chave faltando, em vez de erro, devolve
None("nada", aula O Valor None). - precos.get("bolo", 0)
- O segundo valor é o padrão: o que devolver se a chave não existir. Aqui, 0.
- precos.get("bolo", "não temos")
- O padrão pode ser qualquer coisa, até um texto.
Forma 2: perguntar antes com in
precos = {"pão": 0.50, "leite": 4.75, "café": 18.90}
print("pão" in precos)
print("bolo" in precos)
print("bolo" not in precos)
print(4.75 in precos)
$ python3 di_in.py True False True False
Repare na última linha: 4.75 in precos deu False, embora 4.75 seja o preço do leite. O in num dicionário procura só nas chaves, nunca nos valores. Para procurar nos valores existe precos.values(), da aula Percorrendo um Dicionário.
Missão: o programa mostra quantos pães e quantos bolos há no estoque, mas para com KeyError: 'bolo', porque bolo não está no dicionário. Use get() com o padrão 0 para mostrar Bolos: 0.
estoque = {"pão": 40, "leite": 12}
print("Pães:", estoque["pão"])
print("Bolos:", estoque["bolo"])
estoque = {"pão": 40, "leite": 12}
print("Pães:", estoque.get("pão", 0))
print("Bolos:", estoque.get("bolo", 0))
4. A ordem é a de chegada
Ao contrário do conjunto, o dicionário lembra a ordem em que as chaves entraram. A Ana montou a agenda acrescentando um contato de cada vez (o jeito de acrescentar, agenda["Bia"] = …, é o assunto da próxima aula):
agenda = {}
agenda["Bia"] = "99999-0002"
agenda["Ana"] = "99999-0001"
agenda["Caio"] = "99999-0003"
print(agenda)
$ python3 di_ordem.py
{'Bia': '99999-0002', 'Ana': '99999-0001', 'Caio': '99999-0003'}
A Bia entrou primeiro e aparece primeiro, em toda execução. Não é ordem alfabética: é a ordem de inserção. O Python garante isso desde a versão 3.7. Mesmo assim, o dicionário não tem posição: não existe agenda[0] (veja Quando dá errado); a ordem só aparece quando você mostra ou percorre o dicionário.
5. O que pode ser chave, o que pode ser valor
alunos = {101: "Ana", 102: "Bia"}
print(alunos[101])
distancias = {("Teresina", "Picos"): 306}
print(distancias[("Teresina", "Picos")])
repetida = {"pão": 0.50, "pão": 0.60}
print(repetida)
ficha = {"nome": "Ana", "idade": 34, "notas": [9, 7, 10], "vip": True}
print(ficha["notas"])
$ python3 di_chaves.py
Ana
306
{'pão': 0.6}
[9, 7, 10]
- {101: "Ana", 102: "Bia"}
- Números podem ser chave: aqui, o número de matrícula.
alunos[101]não é "a posição 101", é "a chave 101". - {("Teresina", "Picos"): 306}
- Uma tupla pode ser chave: a distância em km entre duas cidades.
- {"pão": 0.50, "pão": 0.60}
- Cada chave existe uma vez só. Escrita duas vezes, vale a última: sobrou
0.6. Não é erro, por isso é fácil não perceber. - ficha
- Os valores podem ser de qualquer tipo, misturados: texto, número, lista,
True. Um dicionário assim descreve uma coisa (a ficha da Ana) campo por campo.
A regra para as chaves é a mesma dos itens de um conjunto: só valores que não mudam (texto, número, tupla, True/False). Lista não pode ser chave. Os valores, esses, podem ser qualquer coisa, até outro dicionário (aula Dicionários Aninhados).
6. Outras formas de criar: dict()
a = dict(pao=0.50, leite=4.75)
print(a)
b = dict([("pão", 0.50), ("leite", 4.75)])
print(b)
vazio = {}
tambem = dict()
print(vazio, tambem, len(vazio))
$ python3 di_dict.py
{'pao': 0.5, 'leite': 4.75}
{'pão': 0.5, 'leite': 4.75}
{} {} 0
| Forma | Quando usar |
|---|---|
{"pão": 0.50, "leite": 4.75} | Quase sempre. É a forma mais comum e a mais clara |
dict(pao=0.50, leite=4.75) | Quando as chaves são textos simples, que poderiam ser nomes de variável (sem espaço, sem começar com número). Repare que aqui a chave virou 'pao', sem til, porque a Ana escreveu assim |
dict([("pão", 0.50), ("leite", 4.75)]) | Quando os pares já estão numa lista de tuplas |
{} ou dict() | Dicionário vazio, para encher depois |
Lista ou dicionário?
| Situação | Use |
|---|---|
| Uma fila de coisas do mesmo tipo, em que a posição importa (as tarefas do dia, em ordem) | Lista |
| Você procura pelo nome (o preço de cada produto, o telefone de cada pessoa) | Dicionário |
| Os campos de uma ficha (nome, idade, cidade) | Dicionário |
Quando dá errado
precos = {"pão": 0.50, "leite": 4.75, "café": 18.90}
print(precos["Leite"])
$ python3 di_maiuscula.py
Traceback (most recent call last):
File "/home/ana/di_maiuscula.py", line 2, in <module>
print(precos["Leite"])
~~~~~~^^^^^^^^^
KeyError: 'Leite'
Para o dicionário, "Leite" e "leite" são chaves diferentes, como "cafe" e "café". A chave tem de ser igual letra por letra. Como consertar: escreva a chave exatamente como foi guardada. Se a chave vem do teclado, padronize antes: precos[item.lower()] (aula Métodos de Texto).
precos = {"pão": 0.50, "leite": 4.75, "café": 18.90}
print(precos[0])
$ python3 di_indice.py
Traceback (most recent call last):
File "/home/ana/di_indice.py", line 2, in <module>
print(precos[0])
~~~~~~^^^
KeyError: 0
Não é IndexError, como seria numa lista: é KeyError: 0. O dicionário procurou uma chave chamada 0 e não achou. No dicionário, o que vai entre colchetes é sempre uma chave, nunca uma posição. Como consertar: peça pela chave (precos["pão"]). Para "o primeiro par", percorra o dicionário (próximas aulas).
precos = {"pão": 0.50, "leite": 4.75, "café": 18.90}
print(precos[leite])
$ python3 di_semaspas.py
Traceback (most recent call last):
File "/home/ana/di_semaspas.py", line 2, in <module>
print(precos[leite])
^^^^^
NameError: name 'leite' is not defined
Sem aspas, leite é o nome de uma variável, e não existe nenhuma variável com esse nome: "nome 'leite' não está definido". Como consertar: chave de texto vai entre aspas: precos["leite"]. (Sem aspas só faz sentido quando existe mesmo uma variável guardando a chave, como item = "leite" e depois precos[item].)
precos = {"pão": 0.50, "leite": 4.75, "café": 18.90}
print(precos.leite)
$ python3 di_ponto.py
Traceback (most recent call last):
File "/home/ana/di_ponto.py", line 2, in <module>
print(precos.leite)
^^^^^^^^^^^^
AttributeError: 'dict' object has no attribute 'leite'
Quem vem do JavaScript costuma escrever precos.leite. Em Python, o ponto serve para os métodos (precos.get), e o dicionário não tem nada chamado leite. Como consertar: precos["leite"].
estoque = {["arroz", "5kg"]: 12}
$ python3 di_lista_chave.py
Traceback (most recent call last):
File "/home/ana/di_lista_chave.py", line 1, in <module>
estoque = {["arroz", "5kg"]: 12}
^^^^^^^^^^^^^^^^^^^^^^
TypeError: cannot use 'list' as a dict key (unhashable type: 'list')
"Não é possível usar list como chave de dicionário". A lista pode mudar, e uma chave que muda deixaria o dicionário perdido. Como consertar: use uma tupla: {("arroz", "5kg"): 12}. (No Python 3.13 a mensagem é só TypeError: unhashable type: 'list'; a primeira parte é novidade da 3.14.)
Referência rápida
| Escrita | O que faz |
|---|---|
d = {"a": 1, "b": 2} | Cria um dicionário |
d = {} / dict() | Dicionário vazio |
d["a"] | O valor da chave "a"; KeyError se não existir |
d.get("a") | O valor, ou None se a chave não existir |
d.get("a", 0) | O valor, ou 0 se a chave não existir |
"a" in d | True se a chave existe |
len(d) | Quantos pares chave-valor |
dict(pao=1), dict([("pão", 1)]) | Outras formas de criar |
| Mensagem | Causa provável |
|---|---|
KeyError: 'bolo' | A chave não existe (ou está escrita diferente: maiúscula, acento) |
KeyError: 0 | Pediu por posição: dicionário não tem índice |
NameError: name 'leite' is not defined | Chave de texto sem aspas |
AttributeError: 'dict' object has no attribute 'leite' | d.leite no lugar de d["leite"] |
TypeError: cannot use 'list' as a dict key … | Lista como chave: use tupla |
| Um par sumiu, sem erro | Chave repetida na criação: vale a última |
Exercícios
1. Lendo o preço
Complete para mostrar o preço do pão:
2. Sem erro
Complete o método que devolve 0 se a chave "bolo" não existir:
3. Quantos pares?
Quanto vale len({"a": 1, "b": 2, "a": 3})?
4. Com precos = {"pão": 0.50, "leite": 4.75}, o que 0.50 in precos responde?
5. O que {"x": 1}["y"] causa?
6. Qual destes não pode ser chave de um dicionário?
Missão final: o balcão da padaria
Missão: o cliente digita o nome de um produto (a caixa já vai responder leite por ele). Se o produto estiver no dicionário, mostre leite custa R$ 4.75; se não estiver, mostre Não temos …. Use in para perguntar antes, sem deixar o programa parar com KeyError.
precos = {"pão": 0.50, "leite": 4.75, "café": 18.90}
item = input("Qual produto? ")
print("?")
precos = {"pão": 0.50, "leite": 4.75, "café": 18.90}
item = input("Qual produto? ")
if item in precos:
print(f"{item} custa R$ {precos[item]:.2f}")
else:
print(f"Não temos {item}.")
A Ana salvou a solução como balcao.py e rodou no terminal duas vezes; na primeira digitou leite, na segunda bolo:
$ python3 balcao.py Qual produto? leite leite custa R$ 4.75 $ python3 balcao.py Qual produto? bolo Não temos bolo.
Resumo
- O dicionário (
dict) guarda pares chave: valor:{"pão": 0.50, "leite": 4.75}. - Lê-se pela chave, com colchetes:
precos["leite"]. Chave que não existe dáKeyError. get(chave, padrão)devolve o padrão (ouNone) em vez de dar erro;chave in dpergunta se a chave existe (só olha as chaves).- O dicionário guarda a ordem de inserção, mas não tem índice:
d[0]procura a chave0. - Cada chave aparece uma vez; repetida, vale a última. Chaves: texto, número, tupla (lista não). Valores: qualquer coisa.
- A chave tem de ser exata:
"Leite"não é"leite".