Dicionários são estruturas de dados fundamentais em Python, que armazenam pares chave-valor, permitindo acesso rápido e eficiente aos dados. Eles são mutáveis, ordenados (a partir do Python 3.7) e não permitem chaves duplicadas. Nesta aula, você aprenderá a criar, acessar, manipular e iterar sobre dicionários, além de utilizar técnicas avançadas como dict comprehensions.

Entender dicionários é essencial para trabalhar com dados não estruturados, configurações, mapeamentos e muito mais. Vamos explorar desde o básico até padrões mais elegantes e eficientes.

Criação e acesso

Dicionários podem ser criados usando chaves {} com pares chave:valor separados por vírgulas, ou usando o construtor dict(). As chaves devem ser imutáveis (strings, números, tuplas) e os valores podem ser de qualquer tipo.

# Criação com chaves
meu_dict = {'nome': 'Alice', 'idade': 30, 'cidade': 'São Paulo'}

# Criação com dict()
outro_dict = dict(nome='Bob', idade=25, cidade='Rio')

# Dicionário vazio
dict_vazio = {}

Para acessar um valor, usamos a chave entre colchetes. Se a chave não existir, ocorre um erro KeyError. Para evitar isso, podemos usar o método get().

# Acesso
print(meu_dict['nome'])  # Alice

# Tentativa com chave inexistente
# print(meu_dict['pais'])  # KeyError

# Usando get()
print(meu_dict.get('pais'))  # None
print(meu_dict.get('pais', 'Brasil'))  # 'Brasil' (valor padrão)

Também é possível modificar valores ou adicionar novos pares simplesmente atribuindo à chave.

meu_dict['idade'] = 31  # atualiza
meu_dict['profissao'] = 'Engenheira'  # adiciona
print(meu_dict)
# {'nome': 'Alice', 'idade': 31, 'cidade': 'São Paulo', 'profissao': 'Engenheira'}

Métodos (get, items, keys)

Os dicionários possuem diversos métodos úteis. O método get() já foi apresentado. keys() retorna uma visão das chaves, values() retorna os valores, e items() retorna pares (chave, valor) como tuplas.

pessoa = {'nome': 'Carlos', 'idade': 40, 'cidade': 'Brasília'}

# keys()
print(pessoa.keys())  # dict_keys(['nome', 'idade', 'cidade'])

# values()
print(pessoa.values())  # dict_values(['Carlos', 40, 'Brasília'])

# items()
print(pessoa.items())  # dict_items([('nome', 'Carlos'), ('idade', 40), ('cidade', 'Brasília')])

Esses métodos são frequentemente usados em loops para iterar sobre o dicionário. Eles retornam objetos do tipo dict_keys, dict_values e dict_items, que são visões dinâmicas do dicionário (refletem alterações).

Outros métodos importantes: pop(chave) remove e retorna o valor, popitem() remove e retorna o último par inserido, update() atualiza o dicionário com pares de outro dicionário ou iterável, e clear() esvazia o dicionário.

# pop
idade = pessoa.pop('idade')
print(idade)  # 40
print(pessoa)  # {'nome': 'Carlos', 'cidade': 'Brasília'}

# update
pessoa.update({'profissao': 'Médico', 'idade': 41})
print(pessoa)
# {'nome': 'Carlos', 'cidade': 'Brasília', 'profissao': 'Médico', 'idade': 41}

# popitem
ultimo = pessoa.popitem()
print(ultimo)  # ('idade', 41) (ou outro, dependendo da ordem)
print(pessoa)  # {'nome': 'Carlos', 'cidade': 'Brasília', 'profissao': 'Médico'}

Iteração

Podemos iterar sobre dicionários de várias maneiras. O loop padrão for chave in dicionario itera sobre as chaves. Para iterar sobre valores ou pares, usamos .values() e .items().

aluno = {'nome': 'Maria', 'nota': 9.5, 'turma': 'A'}

# Iterando sobre chaves
for chave in aluno:
    print(chave, '->', aluno[chave])

# Iterando sobre valores
for valor in aluno.values():
    print(valor)

# Iterando sobre pares (chave, valor)
for chave, valor in aluno.items():
    print(f'{chave}: {valor}')

É importante lembrar que a ordem de iteração é a ordem de inserção (a partir do Python 3.7). Em versões anteriores, a ordem não era garantida.

Para verificar se uma chave existe, use in:

if 'nome' in aluno:
    print('Chave nome existe')

# Verificar se um valor existe
if 9.5 in aluno.values():
    print('Valor 9.5 existe')

Dict comprehensions

Assim como list comprehensions, podemos criar dicionários de forma concisa usando dict comprehensions. A sintaxe é {chave: valor for item in iterável}.

# Criar dicionário com números ao quadrado
quadrados = {x: x**2 for x in range(5)}
print(quadrados)  # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

# Filtrar com condicional
pares_quadrados = {x: x**2 for x in range(10) if x % 2 == 0}
print(pares_quadrados)  # {0: 0, 2: 4, 4: 16, 6: 36, 8: 64}

# A partir de duas listas
chaves = ['a', 'b', 'c']
valores = [1, 2, 3]
dicionario = {k: v for k, v in zip(chaves, valores)}
print(dicionario)  # {'a': 1, 'b': 2, 'c': 3}

Dict comprehensions são muito úteis para transformar dicionários existentes ou criar mapeamentos rapidamente. Podem incluir expressões complexas e até mesmo aninhamento.

# Inverter chave e valor
dicionario_original = {'a': 1, 'b': 2, 'c': 3}
invertido = {valor: chave for chave, valor in dicionario_original.items()}
print(invertido)  # {1: 'a', 2: 'b', 3: 'c'}

Boas práticas e observações finais

Use get() em vez de acesso direto quando a chave pode não existir, para evitar exceções. Prefira .items() para iteração quando precisar de chave e valor. Dict comprehensions são elegantes, mas evite torná-las muito complexas para manter a legibilidade.

Lembre-se de que dicionários são mutáveis, então cuidado ao passá-los como argumentos para funções, pois alterações internas afetam o original (a menos que você faça uma cópia). Use copy() ou deepcopy() se necessário.

Referências

Exercícios

  1. Crie um dicionário chamado contato com as chaves 'nome', 'email' e 'telefone' e valores de sua escolha. Em seguida, imprima o valor do email usando o método get().

    ✓ Resposta:
    contato = {'nome': 'João', 'email': 'joao@exemplo.com', 'telefone': '1234-5678'}
    print(contato.get('email'))  # joao@exemplo.com
  2. Dado o dicionário estoque = {'maçã': 10, 'banana': 5, 'laranja': 8}, use o método items() para imprimir cada produto e sua quantidade.

    ✓ Resposta:
    estoque = {'maçã': 10, 'banana': 5, 'laranja': 8}
    for produto, qtd in estoque.items():
        print(f'{produto}: {qtd}')
  3. Crie uma dict comprehension que gere um dicionário onde as chaves são números de 1 a 5 e os valores são seus cubos (x**3).

    ✓ Resposta:
    cubos = {x: x**3 for x in range(1, 6)}
    print(cubos)  # {1: 1, 2: 8, 3: 27, 4: 64, 5: 125}
  4. Escreva um código que remova a chave 'cidade' do dicionário pessoa = {'nome': 'Ana', 'idade': 28, 'cidade': 'Curitiba'} usando o método pop() e imprima o valor removido.

    ✓ Resposta:
    pessoa = {'nome': 'Ana', 'idade': 28, 'cidade': 'Curitiba'}
    cidade = pessoa.pop('cidade')
    print(cidade)  # Curitiba
    print(pessoa)  # {'nome': 'Ana', 'idade': 28}
  5. Dado o dicionário notas = {'João': 7.5, 'Maria': 9.0, 'Pedro': 6.5}, crie um novo dicionário apenas com os alunos que têm nota maior ou igual a 8.0, usando dict comprehension.

    ✓ Resposta:
    notas = {'João': 7.5, 'Maria': 9.0, 'Pedro': 6.5}
    aprovados = {aluno: nota for aluno, nota in notas.items() if nota >= 8.0}
    print(aprovados)  # {'Maria': 9.0}