5. Tipos de Dados Compostos#

Anteriormente vimos os tipos básicos de dados em Python, também chamados de tipos primitivos. Agora, veremos o que chamamos de tipos compostos, que nada mais são do que estruturas de dados que permitem armazenar coleções de valores.

Já tivemos um breve contato com estes tipos de dados, na criação de listas em alguns exemplos e usando a função range(), mas agora iremos nos aprofundar mais sobre os tipos de dados compostos.

Tipo Sequencial#

Representam uma coleção ordenada de itens que podem ser acessados por índices. Elas são fundamentais para armazenar e manipular dados de forma estruturada. Dentre suas principais características podemos citar:

  • Ordem definida: Os elementos têm uma posição fixa (índice).

  • Indexação: Acesso aos elementos via índices (começando em 0).

  • Fatiamento (slicing): Extração de subconjuntos usando [início:fim:passo].

  • Iteração: Podem ser percorridas em loops (for, while).

Os principais tipos sequenciais são:

Listas (list)#

É uma coleção ordenada e mutável de itens, podendo conter itens de diferentes tipos (heterogênea). Elas suportam operações como adição, remorção e modificação de itens.

São frequentemente usadas para armazenar coleções de itens que podem precisar ser alterados (adicionados, removidos, modificados), sendo muito versátil.

Para criar uma lista é bem simples, basta usar colchetes [] e separar os itens por vígulas (,).

numeros_primos = [2, 3, 5, 7, 11] # Lista de números inteiros
nomes_alunos = ["Pedro", "Maria", "Carlos"] # Lista de strings
dados_mistos = ["Carla", 10, True, 3.45] # Lista de valores mistos
vazia = [] # Lista vazia

Importante: Os indices de uma lista começam a partir do número 0 e assim segue a sequência dos itens.

EX: [1, 2, 3, 4] seus indices são 1 (indice 0), 2 (indice 1), 3 (indice 2) e 4 (indice 3)

Operações comuns:

  • append() - adiciona um novo item ao final da lista

  • insert() - Insere um item numa posição específica da lista usando índices.

  • pop() - Remove o último item da lista, mas pode-se especificar o indice do item a ser removido.

  • remove() - Remove a primeira ocorrência de um valor específico da lista.

  • sort() - Ordena a lista em ordem crescente ou decrescente, sendo a ordem crescente por padrão (default). Também ordena em ordem alfabética quando trata strings.

lista = [] # Lista vazia
lista.append("Maria") # Adiciona a string à lista
print(lista)

# Insere a string "Pedro" no índice 0, fazendo a str "Maria" ir para o próximo índice
lista.insert(0, "Pedro") 
print(lista)

lista.pop() # Remove o último item da lista
print(lista)

# Criando nova lista com varios itens
novalista = ["Pedro", "Maria", "Murilo", "Carlos"]
print(novalista)

novalista.pop(0) # Removendo item referente ao indice 0 (primeiro item)
print(novalista)

# Cria nova lista repleta de números
lista_numeros = [1,2,3,4,5,2,10,15,4,7,2,3,2]
print(lista_numeros)

# Remove primeiro item da lista que tenha o valor especificado
lista_numeros.remove(2)
print(lista_numeros)
['Maria']
['Pedro', 'Maria']
['Pedro']
['Pedro', 'Maria', 'Murilo', 'Carlos']
['Maria', 'Murilo', 'Carlos']
[1, 2, 3, 4, 5, 2, 10, 15, 4, 7, 2, 3, 2]
[1, 3, 4, 5, 2, 10, 15, 4, 7, 2, 3, 2]
lista_numeros = [10, 25, 1, 3, 4, 8, 22, 4, 5, 9, 4]

lista_numeros.sort() #Ordena a lista em ordem crescente
print(lista_numeros)

lista_numeros.sort(reverse = True) #Ordena a lista em ordem decrescente
print(lista_numeros)

lista_nomes = ["Murilo", "Ana", "Pedro", "Tulio", "Bruno", "Edna", "Amaral"]

lista_nomes.sort() # Ordena a lista em ordem alfabética
print(lista_nomes)

lista_nomes.sort(reverse = True) #Ordena a lista em ordem alfabética invertida
print(lista_nomes)
[1, 3, 4, 4, 4, 5, 8, 9, 10, 22, 25]
[25, 22, 10, 9, 8, 5, 4, 4, 4, 3, 1]
['Amaral', 'Ana', 'Bruno', 'Edna', 'Murilo', 'Pedro', 'Tulio']
['Tulio', 'Pedro', 'Murilo', 'Edna', 'Bruno', 'Ana', 'Amaral']

Tuplas (tuple)#

Assim como listas, tuplas são coleções ordenadas de itens que podem conter itens de diferentes tipos. Entretanto, tuplas são imutáveis, ou seja, uma vez criada, não se pode adicionar, remover ou alterar os itens.

Elas são mais eficientes em memória do que listas, sendo mais rápidas para iterar. Podemos usá-las para proteger nossos dados contra modificações acidentais, chaves em dicionários (veremos mais adiante) e para retornar múltiplos valores em funções (ex: return(x,y)).

Tuplas são frequentemente usadas para armazenar dados fixos (ex coordenadas RGB, data de nascimento). A criação de tuplas se dá pelo uso de parênteses () e separando itens por vírgulas. Veja:

tupla_cores = ("Vermelho", "Verde", "Amarelo") # tupla de strings
tupla_numero = (1, 2, 3, 4) # tupla de numeros
tupla_data_nascimento = (10, "Dezembro", 1995) # tupla de multiplos itens
tupla_vazia = () # tupla vazia

print(tupla_cores)
print(tupla_numero)
print(tupla_data_nascimento)
print(tupla_vazia)
('Vermelho', 'Verde', 'Amarelo')
(1, 2, 3, 4)
(10, 'Dezembro', 1995)
()

Atenção: Para tupla com um único elemento, é necessário usar uma vírgula no final (ex: (item,))

tupla = ("Arthur",)
print(tupla)
('Arthur',)

OBS: Índices de tuplas são iguais aos das listas, começando pelo índice 0.

Função Range()#

A função range() é uma sequência imutável de números gerados sob demanda.

Elas podem ser usadas na geração de índices para acessar outras sequências e para controlar repetições de loops (veremos adiante). A função range() pode receber 3 argumentos, são eles:

  • start: O valor inicial da sequência (por padrão é 0);

  • stop: valor final da sequência (não possui um por padrão). A sequência termina no valor anterior a este;

  • step: incremento entre os valores da sequência (por padrão é 1).

A criação de uma range pode ser feita assim: range(stop), range(start, stop) e range(start, stop, step)..

Exemplos:

# range(stop)
sequencia1 = range(5)          # Gera 0, 1, 2, 3, 4

# range(start, stop)
sequencia2 = range(2, 7)       # Gera 2, 3, 4, 5, 6

# range(start, stop, step)
sequencia3 = range(0, 10, 2)   # Gera 0, 2, 4, 6, 8

Atenção: Range() só pode gerar valores númericos.

Tipo Mapeamento#

Tipos de mapeamento é uma coleção não ordenada e mutável. seus dados são mapeados em pares de chave-valor, onde cada valor é associado a uma chave única, permitindo um acesso eficiente aos dados.

Dicionário (dict)#

É uma coleção não ordenada e mutável de pares de chave-valor. Elas podem receber qualquer tipo de valor e possuem um tempo de busca por chave extremamente eficiente.

São usados para armazenar dados que possuem um relacionamento de chave e valor, como um dicionário de palavras e suas definições, configurações, representação de objetos JSON. Muito eficiente para buscar valores quando você conhece a chave.

São criadas usando chaves {} com pares chave: valor separados por vígula.

  • Chaves: Devem ser únicas e imutáveis (strings, números e tuplas são comumente usados como chaves).

  • Valores: Podem ser de qualquer tipo e podem ser duplicados.

informacao_cliente = {
    "Nome": "Pedro",
    "Idade": 21, 
    "Status": "Ativo"
}

estoque_frutas = {"banana": 100, "maçã": 150, "limão": 70}
dicionario_vazio = {}

OBS: Os valores em dicionários são acessados a partir de suas chaves. Exemplo:

estoque_frutas = {"banana": 100, "maçã": 150, "limão": 70}
print(estoque_frutas["banana"])
100

Tipo conjunto#

Diferente dos tipos anteriores, conjuntos armazenam coleções não ordenadas de itens únicos, ou seja, não é permitido itens duplicados em conjuntos.

conjunto (set())#

É uma coleção não ordenada e mútavel de itens únicos (sem duplicatas).

São usadas para testar se um item pertence a uma coleção, remover duplicatas de uma lista, realizar operações matemáticas de conjutos (união, interserção, diferença)

Sua criação é feita com o uso de chaves {} com itens separados por vírgulas, ou a função set(), pois {} cria um dicionário vázio.

Exemplo:

numeros_unicos = {1,2,3,4,5,5,1,3,4} # armazena os números ignorando duplicatas
letras = set("abacadabra") # armazena as letras separadamente e sem duplicatas
conjunto_vazio = set() # conjunto vázio

print(numeros_unicos)
print(letras)
print(conjunto_vazio)
{1, 2, 3, 4, 5}
{'d', 'b', 'c', 'r', 'a'}
set()

OBS: Conjuntos não suportam indexação e nem fatiamento, seus valores são acessados

Conjunto Congelado (frozenset())#

É uma versão imutável de um set(), ou seja, uma vez criado, não será possível adicionar ou remover itens.

Por serem imutáveis, podem ser usados como chaves em dicionários ou como elementos de outro conjunto.

São criados através da função frozenset().

conjunto_congelado1 = frozenset([5])
conjunto_congelado2 = frozenset([1,2,3,4,4,3,2,2])

print(conjunto_congelado1)
print(conjunto_congelado2)
frozenset({5})
frozenset({1, 2, 3, 4})

Observe que para armazenar os valores você precisa que eles estejam entre colchetes [] dentro da função frozenset().

Extra: Operadores para tipos compostos#

Os operadores de tipos compostos servem para verificar se algum objeto faz parte de um coleção de itens (listas, tuplas, conjuntos) ou se duas ou mais variáveis fazem referência a mesmo objeto na memória.

Operadores de associação (ou Pertencimento / Membership)#

São usados para testar se um valor (ou sequência de valores) é encontrado dentro de uma sequência (como strings, tuplas, conjuntos, chaves de dicionários).

Operador

Nome

Exemplo

Descrição

in

Está contido

5 in [1, 2, 3, 4 , 5]

Retorna True se o valor usado como parâmentro for encontrado na sequência indicada

not in

Não está contido

6 not in [1, 2, 3, 4 , 5]

Retorna True se o valor usado como parâmentro não for encontrado na sequência indicada

Exemplos:

lista_frutas = ["Banana", "Maçã", "Laranja", "Melão"]

# Se tiver a string banana na lista faça
if "Banana" in lista_frutas:
    print("Há bananas na lista de frutas")

# Se tiver a string morango na lista faça
if "Morango" not in lista_frutas:
    print("Não há morangos na lista de fruta")

# Retorna se as afirmações são verdadeiras ou falsas
print(f"{"Banana" not in lista_frutas}") # Não há banana na lista
print(f"{"Morango" in lista_frutas}") # Há morango na lista
Há bananas na lista de frutas
Não há morangos na lista de fruta
False
False

Como foi dito na explicação, Operadores de Associação podem ser usado entre strings também (lembre-se que strings são uma sequência de caracteres). Veja:

sobrenome = "Silva"
nome_completo = "Mario Jóse da Silva"

if sobrenome in nome_completo:
    print("Ele tem silva no nome")

# Verificar se o prefixo "car" está presente na palavra carro
print(f"{"car" in "carro"}")
Ele tem silva no nome
True

Operadores de Identidade#

São usados para verificar se duas variáveis se referem ao mesmo objeto na memória. Para entendermos esse operador, primeiro precisamos entender o que é um objeto na memória.

Objetos na memória#

É um pouco estranho de entender no ínicio, mas o exemplo a seguir vai deixar mais fácil a compreensão.

Exemplo:

a = 10000
b = 10000
c = a      # C recebe o mesmo valor de a

print(a, b, c)
10000 10000 10000

Veja que todas as variáveis possuem o mesmo valor (10000), mas isso não significa que todas referenciam o mesmo objeto na memória.

Aconte que quando criamos uma variável, ele reserva um espaço na memória que guarda o valor que lhe foi atribuido e a variável em si é apenas como uma referência (ponteiro) para o valor salvo na memória, sem conter os valores diretamente.

Então por mais que todas as variáveis possuam o mesmo valor (10000), o endereço onde esse valor está salvo é diferente para todas elas. Usaremos a função id() para vereficar se os IDs das variáveis são iguais:

print(id(a)) # Exibe o endereço de memória da variável
print(id(c)) # Mesmo endereço de a

print(id(b)) # É diferente de a, mas pode ser igual devido a  alguma otimização
140514486538800
140514486538800
140514486537488

Veja que por mais que as variáveis possuam o mesmo valor, alguns IDs (endereço na memória) são diferentes, indicando que seus ponteiros referenciam objetos diferentes na memória.

Repare que a variável c possuí o mesmo endereço que a, isso acontece por que a variável a é atribuida à variável c no trecho c = a. Isso faz o ponteiro de c apontar pro mesmo endereço que o ponteiro de a aponta na memória.

Em resumo, objetos na memória são os endereços lógicos onde ficam salvos os valores que atribuimos às variáveis.

Voltando aos operadores#

Existem apenas 2 operadores de identidade, são eles:

Operador

Nome

Exemplo

Descrição

is

É o mesmo objeto

x is y

Retorna True se x e y apotam para o mesmo objeto na memória

is not

Não é o mesmo objeto

x is not y

Retorna True se x e y não apotam para o mesmo objeto na memória

Exemplos:

a = 10000
b = 10000
c = a

print(a is b) # a e b apontam o mesmo objeto na memória (falso)
print(a is c) # a e c apontam o mesmo objeto na memória (verdadeiro)
print(b is not c) # b e c não apontam o mesmo objeto na memória (verdadeiro)
False
True
True
Diferença entre is e ==#
  • == compara os valores dos operandos.

  • is compara as identidades (IDs) dos objetos (se são o mesmo objeto armazenado na memória)

Resumidamente, use is quando precisar saber se duas variáveis são referências ao mesmo objeto, e == para saber se dois valores são iguais.

Atenção: Para None, é comum e idiomático usar is. Veja o exemplo:

minha_variavel = None

if minha_variavel is None:
    print("Variável vazia")
Variável vazia