Tipos de Dados e Estruturas de Dados

Beginner

This tutorial is from open-source community. Access the source code

Introdução

Esta seção introduz estruturas de dados na forma de tuplas e dicionários.

Este é um Lab Guiado, que fornece instruções passo a passo para ajudá-lo a aprender e praticar. Siga as instruções cuidadosamente para completar cada etapa e ganhar experiência prática. Dados históricos mostram que este é um laboratório de nível iniciante com uma taxa de conclusão de 93%. Recebeu uma taxa de avaliações positivas de 100% dos estudantes.

Tipos de Dados Primitivos

Python possui alguns tipos primitivos de dados:

  • Inteiros (Integers)
  • Números de ponto flutuante (Floating point numbers)
  • Strings (texto)

Aprendemos sobre eles na introdução.

Tipo None

email_address = None

None é frequentemente usado como um espaço reservado para um valor opcional ou ausente. Ele é avaliado como False em condicionais.

if email_address:
    send_email(email_address, msg)

Estruturas de Dados

Programas reais possuem dados mais complexos. Por exemplo, informações sobre uma participação acionária:

100 shares of GOOG at $490.10

Este é um "objeto" com três partes:

  • Nome ou símbolo da ação ("GOOG", uma string)
  • Número de ações (100, um inteiro)
  • Preço (490.10, um float)

Tuplas

Uma tupla é uma coleção de valores agrupados.

Exemplo:

s = ('GOOG', 100, 490.1)

Às vezes, os () são omitidos na sintaxe.

s = 'GOOG', 100, 490.1

Casos especiais (0-tupla, 1-tupla).

t = ()            ## Uma tupla vazia
w = ('GOOG', )    ## Uma tupla de 1 item

Tuplas são frequentemente usadas para representar registros ou estruturas simples. Tipicamente, é um único objeto de múltiplas partes. Uma boa analogia: Uma tupla é como uma única linha em uma tabela de banco de dados.

O conteúdo da tupla é ordenado (como um array).

s = ('GOOG', 100, 490.1)
name = s[0]                 ## 'GOOG'
shares = s[1]               ## 100
price = s[2]                ## 490.1

No entanto, o conteúdo não pode ser modificado.

>>> s[1] = 75
TypeError: object does not support item assignment

Você pode, no entanto, criar uma nova tupla com base em uma tupla atual.

s = (s[0], 75, s[2])

Empacotamento de Tuplas (Tuple Packing)

Tuplas são mais sobre empacotar itens relacionados em uma única entidade.

s = ('GOOG', 100, 490.1)

A tupla é então fácil de passar para outras partes de um programa como um único objeto.

Desempacotamento de Tuplas (Tuple Unpacking)

Para usar a tupla em outro lugar, você pode desempacotar suas partes em variáveis.

name, shares, price = s
print('Cost', shares * price)

O número de variáveis à esquerda deve corresponder à estrutura da tupla.

name, shares = s     ## ERROR
Traceback (most recent call last):
...
ValueError: too many values to unpack

Tuplas vs. Listas (Tuples vs. Lists)

Tuplas se parecem com listas somente leitura. No entanto, tuplas são frequentemente usadas para um único item consistindo em múltiplas partes. Listas são geralmente uma coleção de itens distintos, geralmente todos do mesmo tipo.

record = ('GOOG', 100, 490.1)       ## Uma tupla representando um registro em um portfólio

symbols = [ 'GOOG', 'AAPL', 'IBM' ]  ## Uma Lista representando três símbolos de ações

Dicionários (Dictionaries)

Um dicionário é um mapeamento de chaves para valores. Às vezes, também é chamado de tabela hash (hash table) ou array associativo. As chaves servem como índices para acessar valores.

s = {
    'name': 'GOOG',
    'shares': 100,
    'price': 490.1
}

Operações Comuns (Common operations)

Para obter valores de um dicionário, use os nomes das chaves.

>>> print(s['name'], s['shares'])
GOOG 100
>>> s['price']
490.10
>>>

Para adicionar ou modificar valores, atribua usando os nomes das chaves.

>>> s['shares'] = 75
>>> s['date'] = '6/6/2007'
>>>

Para deletar um valor, use a instrução del.

>>> del s['date']
>>>

Por que dicionários? (Why dictionaries?)

Dicionários são úteis quando há muitos valores diferentes e esses valores podem ser modificados ou manipulados. Dicionários tornam seu código mais legível.

s['price']
## vs
s[2]

Nos últimos exercícios, você escreveu um programa que lia um arquivo de dados portfolio.csv. Usando o módulo csv, é fácil ler o arquivo linha por linha.

>>> import csv
>>> f = open('portfolio.csv')
>>> rows = csv.reader(f)
>>> next(rows)
['name', 'shares', 'price']
>>> row = next(rows)
>>> row
['AA', '100', '32.20']
>>>

Embora a leitura do arquivo seja fácil, você geralmente quer fazer mais com os dados do que apenas lê-los. Por exemplo, talvez você queira armazená-los e começar a realizar alguns cálculos neles. Infelizmente, uma "linha" bruta de dados não fornece o suficiente para trabalhar. Por exemplo, mesmo um cálculo matemático simples não funciona:

>>> row = ['AA', '100', '32.20']
>>> cost = row[1] * row[2]
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
TypeError: can't multiply sequence by non-int of type 'str'
>>>

Para fazer mais, você normalmente quer interpretar os dados brutos de alguma forma e transformá-los em um tipo de objeto mais útil para que possa trabalhar com ele mais tarde. Duas opções simples são tuplas ou dicionários.

Exercício 2.1: Tuplas (Tuples)

No prompt interativo, crie a seguinte tupla que representa a linha acima, mas com as colunas numéricas convertidas em números apropriados:

>>> t = (row[0], int(row[1]), float(row[2]))
>>> t
('AA', 100, 32.2)
>>>

Usando isso, você pode agora calcular o custo total multiplicando as ações e o preço:

>>> cost = t[1] * t[2]
>>> cost
3220.0000000000005
>>>

A matemática está quebrada em Python? Qual é o problema com a resposta 3220.0000000000005?

Este é um artefato do hardware de ponto flutuante (floating point) em seu computador, que só consegue representar com precisão decimais na Base-2, não na Base-10. Mesmo para cálculos simples envolvendo decimais na base 10, pequenos erros são introduzidos. Isso é normal, embora talvez um pouco surpreendente se você não o viu antes.

Isso acontece em todas as linguagens de programação que usam decimais de ponto flutuante, mas muitas vezes fica oculto ao imprimir. Por exemplo:

>>> print(f'{cost:0.2f}')
3220.00
>>>

Tuplas são somente leitura (read-only). Verifique isso tentando mudar o número de ações para 75.

>>> t[1] = 75
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>>

Embora você não possa alterar o conteúdo da tupla, você sempre pode criar uma tupla completamente nova que substitui a antiga.

>>> t = (t[0], 75, t[2])
>>> t
('AA', 75, 32.2)
>>>

Sempre que você reatribui um nome de variável existente como este, o valor antigo é descartado. Embora a atribuição acima possa parecer que você está modificando a tupla, você está realmente criando uma nova tupla e jogando a antiga fora.

Tuplas são frequentemente usadas para empacotar e desempacotar valores em variáveis. Tente o seguinte:

>>> name, shares, price = t
>>> name
'AA'
>>> shares
75
>>> price
32.2
>>>

Pegue as variáveis acima e empacote-as de volta em uma tupla

>>> t = (name, 2*shares, price)
>>> t
('AA', 150, 32.2)
>>>

Exercício 2.2: Dicionários como uma estrutura de dados (data structure)

Uma alternativa a uma tupla é criar um dicionário em vez disso.

>>> d = {
        'name' : row[0],
        'shares' : int(row[1]),
        'price'  : float(row[2])
    }
>>> d
{'name': 'AA', 'shares': 100, 'price': 32.2 }
>>>

Calcule o custo total desta participação:

>>> cost = d['shares'] * d['price']
>>> cost
3220.0000000000005
>>>

Compare este exemplo com o mesmo cálculo envolvendo tuplas acima. Mude o número de ações para 75.

>>> d['shares'] = 75
>>> d
{'name': 'AA', 'shares': 75, 'price': 32.2 }
>>>

Ao contrário das tuplas, os dicionários podem ser livremente modificados. Adicione alguns atributos:

>>> d['date'] = (6, 11, 2007)
>>> d['account'] = 12345
>>> d
{'name': 'AA', 'shares': 75, 'price':32.2, 'date': (6, 11, 2007), 'account': 12345}
>>>

Exercício 2.3: Algumas operações adicionais de dicionário

Se você transformar um dicionário em uma lista, obterá todas as suas chaves:

>>> list(d)
['name', 'shares', 'price', 'date', 'account']
>>>

Da mesma forma, se você usar a instrução for para iterar em um dicionário, obterá as chaves:

>>> for k in d:
        print('k =', k)

k = name
k = shares
k = price
k = date
k = account
>>>

Experimente esta variante que realiza uma pesquisa ao mesmo tempo:

>>> for k in d:
        print(k, '=', d[k])

name = AA
shares = 75
price = 32.2
date = (6, 11, 2007)
account = 12345
>>>

Você também pode obter todas as chaves usando o método keys():

>>> keys = d.keys()
>>> keys
dict_keys(['name', 'shares', 'price', 'date', 'account'])
>>>

keys() é um pouco incomum, pois retorna um objeto especial dict_keys.

Este é um overlay (sobreposição) no dicionário original que sempre lhe dá as chaves atuais - mesmo que o dicionário mude. Por exemplo, tente isto:

>>> del d['account']
>>> keys
dict_keys(['name', 'shares', 'price', 'date'])
>>>

Observe cuidadosamente que 'account' desapareceu de keys, mesmo que você não tenha chamado d.keys() novamente.

Uma maneira mais elegante de trabalhar com chaves e valores juntos é usar o método items(). Isso lhe dá tuplas (chave, valor):

>>> items = d.items()
>>> items
dict_items([('name', 'AA'), ('shares', 75), ('price', 32.2), ('date', (6, 11, 2007))])
>>> for k, v in d.items():
        print(k, '=', v)

name = AA
shares = 75
price = 32.2
date = (6, 11, 2007)
>>>

Se você tiver tuplas como items, pode criar um dicionário usando a função dict(). Experimente:

>>> items
dict_items([('name', 'AA'), ('shares', 75), ('price', 32.2), ('date', (6, 11, 2007))])
>>> d = dict(items)
>>> d
{'name': 'AA', 'shares': 75, 'price':32.2, 'date': (6, 11, 2007)}
>>>

Resumo

Parabéns! Você concluiu o laboratório de Tipos de Dados e Estruturas de Dados. Você pode praticar mais laboratórios no LabEx para aprimorar suas habilidades.