Python Adicionando e Removendo Chaves
Na aula Dicionários, a tabela de preços da padaria já nasceu pronta. Na vida real ela muda o tempo todo: chega um produto novo, o pão sobe de preço, o bolo sai do cardápio. Esta aula mostra como mudar um dicionário depois de criado: acrescentar pares, trocar valores e remover chaves, e um truque que você vai usar muito, o de contar coisas com um dicionário.
- A acrescentar um par e a trocar um valor com a mesma escrita:
d[chave] = valor. - A juntar dois dicionários com
update()e com|. - A remover com
del,pop(),popitem()eclear(), e qual escolher. - A contar quantas vezes cada coisa aparece com
contagem.get(item, 0) + 1. - Os
KeyErrorreais ao remover ou somar numa chave que não existe.
A ideia: o quadro de preços com giz
A padaria do bairro tem um quadro-negro com os preços escritos a giz. Para um produto novo, a Ana escreve uma linha nova. Para mudar um preço, ela apaga só o número e escreve o novo, na mesma linha. Para tirar um produto, apaga a linha inteira. O quadro é o dicionário; o nome do produto, que nunca se repete, é a chave.
1. Acrescentar e trocar: d[chave] = valor
Você já sabe ler com precos["leite"]. Para escrever, é a mesma coisa do lado esquerdo do =:
precos = {"pão": 0.50, "leite": 4.75}
precos["bolo"] = 12.00
print(precos)
precos["pão"] = 0.60
print(precos)
print(len(precos))
$ python3 a_add.py
{'pão': 0.5, 'leite': 4.75, 'bolo': 12.0}
{'pão': 0.6, 'leite': 4.75, 'bolo': 12.0}
3
- precos["bolo"] = 12.00
- A chave
"bolo"não existia: o Python cria o par e o põe no fim (lembre: o dicionário guarda a ordem de chegada). - precos["pão"] = 0.60
- A chave
"pão"já existia: o valor antigo é trocado pelo novo. O pão continua no mesmo lugar, o primeiro. - len(precos)
- Três pares: trocar um valor não cria chave nova.
A mesma linha faz duas coisas: se a chave existe, troca; se não existe, cria. Isso é cômodo, mas tem um lado perigoso: um erro de digitação (precos["paõ"] = 0.60) não dá erro nenhum; cria uma chave nova e deixa o preço do pão como estava.
Os operadores de atribuição (aula Operadores de Atribuição) também funcionam num valor que já existe. Saíram 10 pães e chegaram 6 leites:
estoque = {"pão": 40, "leite": 12}
estoque["pão"] -= 10
estoque["leite"] += 6
print(estoque)
$ python3 a_mais_igual.py
{'pão': 30, 'leite': 18}
Missão: o pão subiu para 0.60 e a padaria passou a vender bolo a 12.00. Antes do print, troque o preço do pão e acrescente o bolo.
precos = {"pão": 0.50, "leite": 4.75}
# mude o dicionário aqui
print(precos)
precos = {"pão": 0.50, "leite": 4.75}
precos["pão"] = 0.60
precos["bolo"] = 12.00
print(precos)
2. Vários de uma vez: update() e |
Chegou a tabela nova do fornecedor, com o leite mais caro e um produto novo. Em vez de uma linha por produto, junte os dois dicionários com update ("atualizar"):
precos = {"pão": 0.60, "leite": 4.75}
novidades = {"leite": 5.10, "café": 18.90}
precos.update(novidades)
print(precos)
precos.update(suco=7.00)
print(precos)
$ python3 a_update.py
{'pão': 0.6, 'leite': 5.1, 'café': 18.9}
{'pão': 0.6, 'leite': 5.1, 'café': 18.9, 'suco': 7.0}
Cada par de novidades é aplicado como um precos[chave] = valor: o leite, que existia, foi trocado; o café, que não existia, foi acrescentado. Na segunda chamada, suco=7.00 é um atalho para chaves de texto simples.
O |: juntar sem mexer no original
O update muda o próprio dicionário. Para um dicionário novo, deixando o original como está, use a barra |, a mesma da união de conjuntos:
loja = {"pão": 0.60, "leite": 4.75}
promocao = {"leite": 3.99}
hoje = loja | promocao
print(hoje)
print(loja)
loja |= {"café": 18.90}
print(loja)
$ python3 a_uniao.py
{'pão': 0.6, 'leite': 3.99}
{'pão': 0.6, 'leite': 4.75}
{'pão': 0.6, 'leite': 4.75, 'café': 18.9}
- loja | promocao
- Um dicionário novo com os pares dos dois. Quando a chave está nos dois (o leite), vale o valor do lado direito.
- print(loja)
- O original não mudou: o leite continua a 4.75.
- loja |= {…}
- Com o
=junto, muda o próprioloja, como oupdate.
O | e o |= entre dicionários existem desde o Python 3.9. O Ubuntu 26.04 (3.14) e o Debian 13 (3.13) já têm; se você encontrar um Python muito antigo, use update.
3. Removendo
Há quatro jeitos de tirar coisas de um dicionário. Todos de uma vez, no estoque da padaria:
estoque = {"pão": 40, "leite": 12, "bolo": 3, "café": 8}
del estoque["bolo"]
print(estoque)
leite = estoque.pop("leite")
print("Tirei o leite, que tinha", leite)
print(estoque)
print(estoque.pop("suco", 0))
ultimo = estoque.popitem()
print(ultimo)
print(estoque)
estoque.clear()
print(estoque)
$ python3 a_del.py
{'pão': 40, 'leite': 12, 'café': 8}
Tirei o leite, que tinha 12
{'pão': 40, 'café': 8}
0
('café', 8)
{'pão': 40}
{}
- del estoque["bolo"]
del("apagar") tira a chave e o valor. Não devolve nada.- estoque.pop("leite")
- "Tirar": remove o par e devolve o valor, que você pode guardar numa variável (aqui, o 12).
- estoque.pop("suco", 0)
- Com um segundo valor, o
popnão dá erro se a chave não existir: devolve esse valor (0) e não remove nada. - estoque.popitem()
- Remove o último par que entrou e o devolve como tupla
(chave, valor):('café', 8). - estoque.clear()
- "Limpar": tira tudo. Sobra
{}, o dicionário vazio.
| Para… | Use | Se a chave não existe |
|---|---|---|
| Tirar uma chave e não precisar do valor | del d[chave] | KeyError |
| Tirar uma chave e usar o valor | d.pop(chave) | KeyError |
| Tirar se existir, sem risco de erro | d.pop(chave, None) | Devolve None |
| Tirar o último par que entrou | d.popitem() | KeyError se estiver vazio |
| Esvaziar | d.clear() | — |
"Renomear" uma chave
Não existe um jeito de mudar o nome de uma chave. O truque é tirar o valor com pop e guardá-lo numa chave nova, numa linha só:
precos = {"pao": 0.60, "leite": 4.75}
precos["pão"] = precos.pop("pao")
print(precos)
$ python3 a_renomear.py
{'leite': 4.75, 'pão': 0.6}
O "pão" foi para o fim, porque é uma chave nova, que acabou de entrar.
Missão: o bolo saiu do cardápio. Tire a chave "bolo" do estoque com pop, guardando quantos bolos havia, para o programa mostrar Bolos retirados: 3 e o estoque sem o bolo.
estoque = {"pão": 40, "leite": 12, "bolo": 3}
bolos = 0
print("Bolos retirados:", bolos)
print(estoque)
estoque = {"pão": 40, "leite": 12, "bolo": 3}
bolos = estoque.pop("bolo")
print("Bolos retirados:", bolos)
print(estoque)
4. O truque de contar
A Ana anotou cada venda do dia numa lista e quer saber quantas vezes cada produto saiu. O dicionário é perfeito para isso: a chave é o produto, o valor é quantas vezes ele apareceu.
vendas = ["pão", "leite", "pão", "café", "pão", "leite"]
contagem = {}
for item in vendas:
contagem[item] = contagem.get(item, 0) + 1
print(contagem)
$ python3 a_contar.py
{'pão': 3, 'leite': 2, 'café': 1}
- Começa com um dicionário vazio.
- Primeiro item,
"pão":contagem.get("pão", 0)não acha a chave e devolve 0; mais 1 dá 1;contagem["pão"] = 1cria a chave. - Segundo item,
"leite": o mesmo,contagem["leite"] = 1. - Terceiro item,
"pão"de novo: agoragetacha o 1; mais 1 dá 2; o valor é trocado por 2. - …e assim até o fim da lista.
O segredo é o get(item, 0): na primeira vez que um produto aparece, ele faz de conta que o valor era zero. A mesma conta, escrita com if, fica mais comprida mas talvez mais fácil de ler no começo:
vendas = ["pão", "leite", "pão", "café", "pão", "leite"]
contagem = {}
for item in vendas:
if item in contagem:
contagem[item] += 1
else:
contagem[item] = 1
print(contagem)
$ python3 a_contar_if.py
{'pão': 3, 'leite': 2, 'café': 1}
Mesmo resultado. Contar é tão comum que o Python tem até uma ferramenta pronta, o Counter, da aula O Módulo collections. Mas vale entender primeiro o jeito "na mão".
setdefault: ler ou criar
Existe também d.setdefault(chave, valor): se a chave existe, devolve o valor dela e não muda nada; se não existe, cria com o valor dado e o devolve.
precos = {"pão": 0.60}
print(precos.setdefault("pão", 1.00))
print(precos.setdefault("bolo", 12.00))
print(precos)
$ python3 a_setdefault.py
0.6
12.0
{'pão': 0.6, 'bolo': 12.0}
Formas diferentes de fazer a mesma coisa
| Objetivo | Formas | Qual usar |
|---|---|---|
| Acrescentar ou trocar um par | d["k"] = v · d.update({"k": v}) | d["k"] = v para um par; update para vários |
| Juntar dois dicionários | a.update(b) · a |= b · c = a | b | a | b quando quer manter o original; os outros mudam a |
| Remover uma chave | del d["k"] · d.pop("k") | pop quando vai usar o valor; del quando não |
| Remover sem risco de erro | d.pop("k", None) · if "k" in d: del d["k"] | O pop com padrão, mais curto |
| Contar | d[x] = d.get(x, 0) + 1 · if/else | O get, que é o costume |
Quando dá errado
A forma mais curta de contar parece ser contagem[item] += 1. Mas:
vendas = ["pão", "leite", "pão"]
contagem = {}
for item in vendas:
contagem[item] += 1
$ python3 a_contar_erro.py
Traceback (most recent call last):
File "/home/ana/a_contar_erro.py", line 4, in <module>
contagem[item] += 1
~~~~~~~~^^^^^^
KeyError: 'pão'
- line 4
- O erro está na linha 4, dentro do
for, logo na primeira volta. - contagem[item] += 1
- É o mesmo que
contagem[item] = contagem[item] + 1. Para somar 1, o Python precisa primeiro lercontagem["pão"]… - KeyError: 'pão'
- …e essa chave ainda não existe. Não há valor antigo para somar.
Como consertar: contagem[item] = contagem.get(item, 0) + 1, ou o if item in contagem da seção 4.
estoque = {"pão": 40, "leite": 12}
del estoque["bolo"]
$ python3 a_del_erro.py
Traceback (most recent call last):
File "/home/ana/a_del_erro.py", line 2, in <module>
del estoque["bolo"]
~~~~~~~^^^^^^^^
KeyError: 'bolo'
O mesmo KeyError da leitura: não há bolo para apagar. Com pop sem padrão acontece igual:
estoque = {"pão": 40, "leite": 12}
estoque.pop("bolo")
$ python3 a_pop_erro.py
Traceback (most recent call last):
File "/home/ana/a_pop_erro.py", line 2, in <module>
estoque.pop("bolo")
~~~~~~~~~~~^^^^^^^^
KeyError: 'bolo'
Como consertar: estoque.pop("bolo", None) remove se existir e fica quieto se não existir.
popitem() num dicionário vazio
estoque = {}
estoque.popitem()
$ python3 a_popitem_erro.py
Traceback (most recent call last):
File "/home/ana/a_popitem_erro.py", line 2, in <module>
estoque.popitem()
~~~~~~~~~~~~~~~^^
KeyError: 'popitem(): dictionary is empty'
Aqui o KeyError vem com uma frase em vez do nome de uma chave: "popitem(): o dicionário está vazio". Como consertar: confira antes: if estoque: estoque.popitem() (dicionário vazio conta como falso).
precos["paõ"] = 0.60 (com o til no lugar errado) não dá erro nenhum. Como a chave "paõ" não existe, o Python a cria, e o dicionário fica com o pão antigo e mais um "paõ" novo. Como perceber: mostre o dicionário depois de mudar, ou confira o len: se ele cresceu quando você só queria trocar um preço, alguma chave saiu escrita diferente.
Referência rápida
| Escrita | O que faz |
|---|---|
d[k] = v | Cria o par (chave nova) ou troca o valor (chave existente) |
d[k] += 1 | Soma no valor existente (KeyError se a chave não existe) |
d.update(outro) | Aplica todos os pares de outro em d |
a | b / a |= b | Dicionário novo com os dois / muda a (vale o da direita) |
del d[k] | Remove a chave |
d.pop(k) / d.pop(k, padrao) | Remove e devolve o valor / sem erro se não existir |
d.popitem() | Remove e devolve o último par, como tupla |
d.clear() | Esvazia |
d.setdefault(k, v) | Devolve o valor de k; se não existir, cria com v |
d[x] = d.get(x, 0) + 1 | Conta quantas vezes x aparece |
| Mensagem | Causa provável |
|---|---|
KeyError: 'pão' numa linha com += | Somou numa chave que ainda não existe: use get(k, 0) + 1 |
KeyError: 'bolo' num del ou pop | A chave não existe: use pop(k, None) |
KeyError: 'popitem(): dictionary is empty' | popitem() com o dicionário vazio |
O len cresceu quando era só trocar | Chave escrita diferente: virou chave nova |
Exercícios
1. Produto novo
Complete para acrescentar o suco a 7.00:
2. Apagar
Complete a palavra que apaga a chave "bolo":
3. Contando
Complete o valor padrão do get na linha que conta:
4. Com d = {"a": 1}, o que acontece em d["a"] = 5?
5. Qual remove a chave "x" e devolve o valor dela?
6. Em {"leite": 4.75} | {"leite": 3.99}, qual preço do leite fica?
Missão final: a votação do sorvete
Missão: a turma votou no sabor do sorvete da festa. O programa quer contar os votos de cada sabor, mas para com KeyError: 'morango'. Conserte a linha de dentro do for.
votos = ["morango", "chocolate", "morango", "coco", "morango", "chocolate"]
contagem = {}
for sabor in votos:
contagem[sabor] += 1
print(contagem)
votos = ["morango", "chocolate", "morango", "coco", "morango", "chocolate"]
contagem = {}
for sabor in votos:
contagem[sabor] = contagem.get(sabor, 0) + 1
print(contagem)
Resumo
d[chave] = valorcria o par se a chave é nova e troca o valor se ela já existe.update()aplica vários pares de uma vez;a | bcria um dicionário novo (vale o valor da direita);|=muda o próprio.del d[k]remove;d.pop(k)remove e devolve;d.pop(k, None)não dá erro;popitem()tira o último par;clear()esvazia.- Para contar:
contagem[x] = contagem.get(x, 0) + 1. Ocontagem[x] += 1sozinho dáKeyErrorna primeira vez. - Cuidado com chave digitada errado: não dá erro, vira chave nova.