Curso de Python / Dicionários: chaves, valores e totais por categoria
Um dicionário encontra valores por meio de chaves. Ele é útil para registros com campos nomeados e para totais por categoria; ao consultar uma chave ausente, defina se essa ausência deve ser um erro ou se um valor padrão faz sentido.
Entenda as chaves e a substituição de valores
Um literal de dicionário usa chaves e pares no formato chave: valor. Atribuir novamente à mesma chave substitui o valor anterior, em vez de criar uma segunda ocorrência dessa chave. Execute este pequeno exemplo para observar a atualização:
expense = {"name": "lunch", "amount": 8000}
expense["amount"] = 9000
print(expense["amount"])
O resultado é 9000. O campo amount passou a ter o novo valor, e o dicionário continua tendo duas chaves: name e amount. A iteração preserva a ordem de inserção, mas não ordena automaticamente por nome ou por valor. Peça uma ordenação explícita quando essa for a regra de apresentação.
As chaves precisam ser hashable: devem fornecer um hash estável durante sua existência, e objetos iguais devem ter hashes iguais. Strings e inteiros são opções comuns; listas não são hashable. Uma tupla que contém uma lista também não pode ser chave. Essa condição é explicada no glossário oficial de Python e complementa a aula sobre tuplas e desempacotamento.
Chaves de texto diferenciam maiúsculas, minúsculas e espaços. "food", "Food" e " food " são três chaves diferentes. Decida se essas diferenças têm significado antes de normalizar os dados.
Calcule os totais de despesas por categoria
Salve o programa completo em UTF-8 como dicts.py, na pasta do projeto, e execute python dicts.py com o ambiente selecionado. No macOS ou Ubuntu, fora de um ambiente virtual, use python3 se esse for o comando disponível. Não são necessários pacotes nem arquivos externos.
expenses = [("food", 8000), ("transport", 2500), ("food", 3500)]
totals = {}
for category, amount in expenses:
totals[category] = totals.get(category, 0) + amount
for category, total in sorted(totals.items()):
print(category, total)
print(totals.get("books", 0))
A saída esperada é:
food 11500
transport 2500
0
A primeira repetição percorre os pares de categoria e valor. Para a primeira despesa de uma categoria, get(category, 0) fornece o zero inicial; depois, o programa soma o valor e atribui o resultado à chave. As duas despesas de food resultam em 11500, e transport fica com 2500.
Na segunda repetição, items() fornece os pares de chave e valor, e sorted() define uma ordem de saída pelas chaves desses pares. A última linha consulta a categoria ausente books com o padrão zero. Os textos em inglês são os dados de categoria usados no exemplo.
Escolha entre uma consulta obrigatória e um padrão
Em um dict comum, totals["books"] provoca KeyError quando a chave não existe. totals.get("books", 0) retorna 0 nesse caso, sem inserir a chave. A referência do tipo dict descreve as duas formas.
O padrão de get() é usado somente para uma chave ausente. Se a chave existir com o valor None, get("books", 0) retorna None, não zero. Também não verifica se um valor existente é numérico ou pertence à unidade esperada.
Um padrão zero é adequado para começar uma soma por categoria, mas pode esconder um registro inválido quando um campo é obrigatório. Para verificar a presença, use uma expressão como "amount" in expense. Não confunda ausência de um valor com um valor zero que foi informado corretamente.
Ao percorrer o dicionário diretamente, você recebe as chaves. Use values() para os valores ou items() para os pares. Uma cópia com dict.copy() é rasa: se um valor for uma lista, a cópia ainda pode compartilhar essa lista interna com o original.
Se o padrão de acumular a partir de zero aparecer muitas vezes, a biblioteca padrão oferece defaultdict(int). Ao acessar uma chave ausente com colchetes, ele cria o valor inicial; seu get(), porém, continua tendo o comportamento normal de consulta. Escolha a ferramenta sabendo se a consulta deve ou não modificar o dicionário.
Teste a normalização e as mudanças na coleção
- Troque somente
3500por4500no último registro deexpenses. Confirafood 12500, mantendotransport 2500. - Restaure o valor. Troque apenas a categoria do primeiro registro de
foodparaFood. A saída terá grupos separados:Food 8000efood 3500, além detransport 2500. - Restaure a categoria e confirme novamente as três linhas originais. Se
booksfor obrigatório em outra aplicação, confira sua presença, em vez de usar o zero como prova de que o dado existe.
Acrescentar ou remover chaves durante a iteração sobre o mesmo dicionário pode provocar RuntimeError. Reúna as chaves de interesse antes de alterar a coleção ou crie um novo dicionário com o resultado. Separe a etapa de identificar os registros da etapa de modificar a estrutura, para não depender de uma coleção cujo tamanho muda durante o percurso.




