Dicionários em Python - #12
Tags: beginners, tutorial, programming, python
Published: 2022-07-12 22:26:26

{% youtube https://youtu.be/HDaLd9RVJio %}

## Introdução

Dicionários são coleções de objetos semelhantes às listas e tuplas. A principal diferença é que os dicionários armazenam uma “chave” para cada “valor”, desta forma, no jargão computacional os dicionários são mapas em _Python_.

Parece confuso, mas vamos explorar este conceito nas próximas seções.

## Sintaxe

Dicionários ou mapas armazenam dois valores por cada elemento: uma chave e um valor. É uma estrutura de dados cuja principal finalidade é localizar elementos de forma rápida.

Utilizamos um mapa porque **dada uma chave, você encontra um valor. Não existem chaves repetidas em um mapa.**

Um dicionário é criado com o uso de **_chaves (“{ }”)_** e cada par **_chave, valor_** é identificado por **_dois pontos (“:”)_** e separados por **_vírgula (“,”)_**.

```python
#Sintaxe - criando dicionários
>>> mapa_cores = {"Joao":"preto", "Lara":"rosa", "Jose":"azul"}
>>> print(mapa_cores)
{'Joao': 'preto', 'Lara': 'rosa', 'Jose': 'azul'}

>>> mapa_cores_2 = {"Joao":"preto", "Lara":"rosa", "Joao":"azul"}
>>> print(mapa_cores_2)
{'Joao': 'azul', 'Lara': 'rosa'}
```

No _mapa_cores_2_ do exemplo anterior, usamos a mesma chave _‘Joao’_ duas vezes, com os valores _“preto”_ e “azul” respectivamente. Como as chaves não podem se repetir em um dicionário, o último valor prevalece, e o resultado é o par _“Joao”:“azul”_.

Também podemos usar dicionários para representar informações de algo em particular, por exemplo, um aluno.

```python
#Sintaxe - representando informações específicas
>>> aluno = {"nome":"Lara", "sexo":"feminino", "idade":15, "altura":1.65}

>>> print(aluno)
{'nome': 'Lara', 'sexo': 'feminino', 'idade': 15, 'altura': 1.65}
```

## Manipulando valores

Enquanto as listas utilizam um índice baseado na posição do elemento (índices começando na posição ZERO), **os dicionários usam as chaves como índices**.

### Acessando valores com a chave

Se queremos ler um valor, devemos usar o valor da chave. Também é possível atualizar o valor, utilizando a chave como índice.

```python
#Manipulando valores em um dicionário
>>> mapa_cores = {"Joao":"preto", "Lara":"rosa", "Jose":"azul"}
>>> print(mapa_cores)
{'Joao': 'preto', 'Lara': 'rosa', 'Jose': 'azul'}
>>> print(mapa_cores['Lara'])
rosa

>>> aluno = {"nome":"Lara", "sexo":"feminino", "idade":15, "altura":1.65}
>>> print("Idade da aluna %s = %s" % (aluno["nome"], aluno["idade"]))
Idade da aluna Lara = 15
```

### Acessando valores - **_get()_**

Outra forma de acessar os valores de um dicionário é através do método **_get()_**.

```python
#Sintaxe - get()
<mapa>.get(<nome_chave>, <retorno_padrao>)
```

Usando o **_get()_** se a chave não existir no mapa, será retornado um valor padrão definido pelo programador.

```python
#Usando o get()
>>> mapa_cores = {'Joao': 'preto', 'Lara': 'rosa'}
>>> mapa_cores.get('Joao', 'azul')
'preto'
>>> mapa_cores.get('Jose', 'azul')
'azul'
>>> print(mapa_cores.get('Jose'))
None
```

A chave _‘Jose’_ não existe no mapa, então é retornado o valor ‘azul’. Caso você não forneça um valor padrão, será retornado o valor **_None_**.

### Inserindo valores com a chave

Inserir valores em dicionários é mais simples do que em listas. Basta utilizar o dicionário e atribuir um novo valor para uma nova chave.

```python
#Inserindo valores em um dicionário
>>> mapa_cores = {"Joao":"preto", "Lara":"rosa", "Jose":"azul"}
>>> print(mapa_cores)
{'Joao': 'preto', 'Lara': 'rosa', 'Jose': 'azul'}

>>> mapa_cores['Raul'] = 'vermelho'
>>> print(mapa_cores)
{'Joao': 'preto', 'Lara': 'rosa', 'Jose': 'azul', 'Raul': 'vermelho'}

>>> aluno = {"nome":"Lara", "idade":15}
>>> print(aluno)
{'nome': 'Lara', 'idade': 15}

>>> aluno["signo"] = "cancer"
>>> print(aluno)
{'nome': 'Lara', 'idade': 15, 'signo': 'cancer'}
```

### Inserindo valores - **_setdefault()_**

O método **_setdefault()_** permite adicionar um valor padrão **<span style="text-decoration:underline;">quando uma chave não existe</span>** no dicionário.

```python
#Inserindo valores em um dicionário com setdefault()
>>> aluno = {"nome":"Lara"}
>>> aluno
{'nome': 'Lara'}

>>> aluno.setdefault("idade", 15)
15
>>> aluno
{'nome': 'Lara', 'idade': 15}

>>> aluno.setdefault("idade", 20)
15
>>> aluno
{'nome': 'Lara', 'idade': 15}
```

Observe que ao executarmos o **_setdefault()_** mais de uma vez, o valor não será mais alterado porque a chave já existe.

### Removendo valores - **_del_**

O comando **_del_** também é utilizado para remover a **_chave_** e **_valor_**.

```python
#Removendo valores em um dicionário
>>> mapa_cores = {"Joao":"preto", "Lara":"rosa", "Jose":"azul"}
>>> print(mapa_cores)
{'Joao': 'preto', 'Lara': 'rosa', 'Jose': 'azul'}

>>> del mapa_cores['Joao']

>>> print(mapa_cores)
{'Lara': 'rosa', 'Jose': 'azul'}
```

## Percorrendo dicionários

### Lendo com **_items()_**

Utilizando um laço **_for_** podemos ler a chave e o valor de um mapa, invocando o método **_items()_**.

```python
#Sintaxe - usando for para ler dicionários
for <variavel_key>, <variavel_value> in <mapa>.items():
```

```python
#Programa - lerMapa.py
usuario = {
    'nome':'Maria',
    'idade':38,
    'sexo':'F'
}

for key, value in usuario.items():
    print(f"\nChave: {key}")
    print(f"Valor: {value}")
```

Nas linhas 01 a 05 criamos um mapa com 3 chaves: **_nome, idade, sexo_**. E usando a sintaxe **_for_** da linha 07 imprimimos as chaves e valores.

```
#Execução - usando for para ler dicionários
Chave: nome
Valor: Maria

Chave: idade
Valor: 38

Chave: sexo
Valor: F
```

Um algoritmo interessante usando o **_setdefault()_** e o **_for_** é o de contar os caracteres de uma **_string_**.

Implemente no seu ambiente.

```python
#texto = input("Digite um texto: ")
count = {}
for letra in texto:
    count.setdefault(letra, 0)
    count[letra] += 1

print(count)
```

Você consegue entender o código acima? O método **_setdefault()_** é utilizado para criar um valor padrão na contagem de uma letra encontrada, caso não exista no dicionário, igual a ZERO. Desta forma, podemos manipular o campo (linha 05), incrementando o valor daquela chave. Se não tivéssemos usado o método para indicar um valor padrão, o código acima geraria um erro, uma vez que a chave não estaria presente no dicionário.

```
#Execução - countChar.py
Digite um texto: abacaxi
{'a': 3, 'b': 1, 'c': 1, 'x': 1, 'i': 1}
```

### Lendo com **_keys()_**

O método **_keys()_** retorna a lista de chaves de um dicionário.

```python
#Programa - usarKeys.py
usuario = {
    'nome':'Maria',
    'idade':38,
    'sexo':'F'
}

print("Usando Keys())")
for key in usuario.keys():
    print(f"Chave: {key}")

print("\nSem usar Keys())")
for key in usuario:
    print(f"Chave: {key}")
```

Na linha 12 do código anterior, é possível navegar usando somente o nome do dicionário.

```
#Execução - usarKeys.py
Usando Keys())
Chave: nome
Chave: idade
Chave: sexo

Sem usar Keys())
Chave: nome
Chave: idade
Chave: sexo
```

### Lendo com **_values()_**

O método **_values()_** retorna a lista de valores de um mapa.

```python
#Programa - usarValues.py
cores = {
    'Jose':'preto',
    'Leo':'branco',
    'Edu': 'amarelo'
}

for cor in cores.values():
    print(f"Cor: {cor}")
```

```
#Execução - usarValues.py
Cor: preto
Cor: branco
Cor: amarelo
```

## Utilizando listas e dicionários

Listas, tuplas e dicionários são tipos de dados semelhantes aos numéricos, booleanos e **_strings_**. Desta forma podemos criar listas de dicionários, dicionários de listas, e outras variações.

### Lista de dicionário

Neste exemplo, vamos criar uma lista de dicionários, representando uma turma escolar, e cada dicionário representando um aluno. Cada aluno possui uma média, e este programa irá indicar se o aluno reprovou (média &lt; 4), ficará de recuperação (média &lt; 7) ou se ele foi aprovado (médica >= 7).

```python
#Programa - alunosAprovados.py
turma = [
    {'nome':'Paulo', 'media':5.5},
    {'nome':'Lara', 'media':8.5},
    {'nome':'Joca', 'media':3.2},
    {'nome':'Ze', 'media':7.0},
    {'nome':'Edu', 'media':2.4}
]

for aluno in turma:
    if aluno['media'] < 4.0:
        print(f"Aluno {aluno['nome']}: REPROVADO")
    elif aluno['media'] < 7.0:
        print(f"Aluno {aluno['nome']}: RECUPERACAO")
    else:
        print(f"Aluno {aluno['nome']}: APROVADO")
```

```python
#Execução - usarValues.py
Aluno Paulo: RECUPERACAO
Aluno Lara: APROVADO
Aluno Joca: REPROVADO
Aluno Ze: APROVADO
Aluno Edu: REPROVADO
```

Podemos também implementar um dicionário de lista para salvar as notas de um aluno e calcular sua média.

```python
#Programa - mediaAluno.py
aluno_01 = {
    "nome" : "Joel",
    "notas": [7.7, 10, 8.3]
}
aluno_02 = {
    "nome" : "Coringa",
    "notas": [3.2, 8, 4.0]
}
aluno_03 = {
    "nome" : "Batman",
    "notas": [8, 9, 10]
}

turma = [aluno_01, aluno_02, aluno_03]

#calcular media
for aluno in turma:
    notas = aluno["notas"]
    media = sum(notas) / len(notas)
    aluno["media"] = media

#imprimindo turma com media
print(turma)
```

Nas linhas 01 a 12 é criado 3 variáveis do tipo dicionário, representando 3 alunos, com nome e uma lista de notas.

Na linha 14 criamos uma turma como uma lista de alunos.

O laço **_for_** lê cada aluno na turma, e utilizando a variável **_aluno_**, calcula a sua média (somando as notas e dividindo pela quantidade de notas) e salvando no dicionário representado por **_aluno_**.

Finalmente, podemos implementar o exemplo dos alunos aprovados com a turma sendo representada como dicionário de dicionários.

```python
#Programa - alunosAprovadosUsandoDicionario.py
turma = {
    'Paulo' : {'nome':'Paulo', 'media':5.5},
    'Lara' : {'nome':'Lara', 'media':8.5},
    'Joca' : {'nome':'Joca', 'media':3.2},
    'Ze' : {'nome':'Ze', 'media':7.0},
    'Edu' : {'nome':'Edu', 'media':2.4}
}

for nome, dados in turma.items():
    if dados['media'] < 4.0:
        print(f"Aluno {nome}: REPROVADO")
    elif dados['media'] < 7.0:
        print(f"Aluno {nome}: RECUPERACAO")
    else:
        print(f"Aluno {nome}: APROVADO")
```

```
#Execução - alunosAprovadosUsandoDicionario.py
Aluno Paulo: RECUPERACAO
Aluno Lara: APROVADO
Aluno Joca: REPROVADO
Aluno Ze: APROVADO
Aluno Edu: REPROVADO
```

## Erros comuns

Dicionários são estruturas **_chave-valor_**, não podemos usar chaves inexistentes na lógica de nossos programas.

```python
#Usando chaves inexistentes geram erros na execução
>>> mapa_cores = {"Joao":"preto", "Lara":"rosa"}

>>> print(mapa_cores['Zezinho'])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'Zezinho'

>>> del mapa_cores['Raul']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'Raul'
```

Também não é possível fazer a junção (“+”) com dicionários.

```python
#operação de junção não suportada
>>> mapa_cor_um = {"Joao":"preto"}
>>> mapa_cor_dois = {"Lara":"rosa"}

>>> mapa_cor_um + mapa_cor_dois
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'dict' and 'dict'
```