Coleções em Python
Introdução
As coleções em Python são estruturas de dados que permitem armazenar múltiplos itens em uma única variável. Estas estruturas funcionam como contêineres e oferecem diferentes formas de organizar e manipular dados, cada uma com características específicas de acesso, mutabilidade e ordenação.
Objetivos de Aprendizado
- Entender os diferentes tipos de coleções disponíveis em Python
- Aprender a utilizar listas, tuplas, dicionários e conjuntos
- Compreender quando usar cada tipo de coleção
- Dominar os métodos e operações disponíveis para cada coleção
- Aplicar coleções em situações práticas
Tipos de Coleções
Python oferece quatro tipos principais de coleções:
- Listas - Coleções ordenadas e mutáveis
- Tuplas - Coleções ordenadas e imutáveis
- Dicionários - Coleções não-ordenadas (em versões < 3.7) de pares chave-valor
- Conjuntos - Coleções não-ordenadas de itens únicos
Listas (Lists)
Listas são coleções ordenadas e mutáveis, permitindo itens duplicados.
# Diferentes maneiras de criar listas
numeros = [1, 2, 3, 4, 5]
frutas = ["maçã", "banana", "laranja"]
misturada = [1, "Python", True, 3.14]
vazia = []
# Criando listas com a função list()
lista_de_string = list("Python") # ['P', 'y', 't', 'h', 'o', 'n']
lista_de_range = list(range(5)) # [0, 1, 2, 3, 4]
frutas = ["maçã", "banana", "laranja", "uva", "pêra"]
# Indexação começa em 0
primeira = frutas[0] # "maçã"
terceira = frutas[2] # "laranja"
# Índices negativos contam de trás para frente
ultima = frutas[-1] # "pêra"
penultima = frutas[-2] # "uva"
# Fatiamento (slicing)
primeiras_tres = frutas[0:3] # ["maçã", "banana", "laranja"]
do_inicio = frutas[:2] # ["maçã", "banana"]
ate_o_fim = frutas[2:] # ["laranja", "uva", "pêra"]
copia_completa = frutas[:] # Cria uma cópia da lista
pulo_dois = frutas[::2] # ["maçã", "laranja", "pêra"] (passo 2)
invertida = frutas[::-1] # ["pêra", "uva", "laranja", "banana", "maçã"]
frutas = ["maçã", "banana", "laranja"]
# Alterando um elemento específico
frutas[1] = "morango" # ["maçã", "morango", "laranja"]
# Adicionando elementos
frutas.append("uva") # Adiciona ao final: ["maçã", "morango", "laranja", "uva"]
frutas.insert(1, "abacaxi") # Insere na posição 1: ["maçã", "abacaxi", "morango", "laranja", "uva"]
frutas.extend(["pêra", "limão"]) # Adiciona vários: ["maçã", "abacaxi", "morango", "laranja", "uva", "pêra", "limão"]
# Removendo elementos
frutas.remove("morango") # Remove por valor: ["maçã", "abacaxi", "laranja", "uva", "pêra", "limão"]
item_removido = frutas.pop(1) # Remove por índice e retorna: "abacaxi"
ultimo = frutas.pop() # Remove e retorna o último item: "limão"
del frutas[0] # Remove por índice, sem retornar: ["laranja", "uva", "pêra"]
# Operações comuns
frutas.clear() # Esvazia a lista: []
numeros = [3, 1, 4, 1, 5, 9, 2, 6]
# Ordenação
numeros.sort() # [1, 1, 2, 3, 4, 5, 6, 9]
numeros.sort(reverse=True) # [9, 6, 5, 4, 3, 2, 1, 1]
# Não modifica a lista original
ordenada = sorted(numeros) # Retorna uma nova lista ordenada
# Invertendo
numeros.reverse() # Inverte a ordem dos elementos
# Contagem e localização
contagem = numeros.count(1) # Retorna quantas vezes 1 aparece
indice = numeros.index(5) # Retorna o índice da primeira ocorrência de 5
# Comprimento
tamanho = len(numeros) # Retorna o número de elementos na lista
Dica: Compreensão de Listas
As compreensões de listas (list comprehensions) oferecem uma forma concisa e elegante de criar listas:
# Criando uma lista com os quadrados dos números de 1 a 10
quadrados = [x**2 for x in range(1, 11)] # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
# Filtrando apenas números pares
pares = [x for x in range(1, 11) if x % 2 == 0] # [2, 4, 6, 8, 10]
# Criando uma matriz 3x3
matriz = [[i * 3 + j + 1 for j in range(3)] for i in range(3)]
# [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Tuplas (Tuples)
Tuplas são coleções ordenadas e imutáveis, permitindo itens duplicados. Uma vez criada, uma tupla não pode ser modificada.
# Diferentes formas de criar tuplas
coordenadas = (10, 20)
cores = ("vermelho", "verde", "azul")
misturada = (1, "Python", True)
# Tupla de um elemento (precisa da vírgula)
singleton = (42,) # Sem a vírgula seria apenas um inteiro entre parênteses
# Criando tuplas com a função tuple()
tupla_de_lista = tuple([1, 2, 3]) # (1, 2, 3)
tupla_de_string = tuple("Python") # ('P', 'y', 't', 'h', 'o', 'n')
# Tupla sem parênteses (empacotamento)
pessoa = "João", 30, "Engenheiro" # ("João", 30, "Engenheiro")
cores = ("vermelho", "verde", "azul", "amarelo", "roxo")
# Acessando elementos (semelhante às listas)
primeira_cor = cores[0] # "vermelho"
ultima_cor = cores[-1] # "roxo"
# Fatiamento (slicing)
primeiras_tres = cores[0:3] # ("vermelho", "verde", "azul")
# Tentando modificar uma tupla gera um erro
# cores[0] = "preto" # TypeError: 'tuple' object does not support item assignment
# Desempacotamento - atribuindo elementos a variáveis
pessoa = ("João", 30, "Engenheiro")
nome, idade, profissao = pessoa # nome="João", idade=30, profissao="Engenheiro"
# Usando _ para ignorar valores
coordenadas = (10, 20, 30)
x, _, z = coordenadas # x=10, z=30, ignorando o valor do meio
# Desempacotando com *
numeros = (1, 2, 3, 4, 5)
primeiro, *meio, ultimo = numeros # primeiro=1, meio=[2, 3, 4], ultimo=5
cores1 = ("vermelho", "verde")
cores2 = ("azul", "amarelo")
# Concatenação
todas_cores = cores1 + cores2 # ("vermelho", "verde", "azul", "amarelo")
# Repetição
repetida = cores1 * 3 # ("vermelho", "verde", "vermelho", "verde", "vermelho", "verde")
# Verificando se um elemento existe
tem_verde = "verde" in cores1 # True
# Contagem e localização (mesmos métodos das listas)
contagem = todas_cores.count("verde") # Retorna quantas vezes "verde" aparece
indice = todas_cores.index("azul") # Retorna o índice da primeira ocorrência de "azul"
Por que usar Tuplas?
- Tuplas são imutáveis, o que as torna adequadas para dados que não devem ser alterados.
- Podem ser usadas como chaves de dicionários (listas não podem).
- Geralmente mais rápidas que listas para operações comuns.
- Indicam claramente que os dados não devem ser modificados.
Dicionários (Dictionaries)
Dicionários são coleções de pares chave-valor, não-ordenadas (antes do Python 3.7) ou ordenadas (a partir do Python 3.7) pela ordem de inserção, mutáveis e sem duplicatas nas chaves.
# Diferentes formas de criar dicionários
pessoa = {"nome": "Ana", "idade": 30, "profissao": "Engenheira"}
pontos = {1: "A", 2: "B", 3: "C"}
misturado = {"chave": 1, 2: "valor", "lista": [1, 2, 3]}
vazio = {}
# Criando com a função dict()
pessoa2 = dict(nome="Carlos", idade=25, profissao="Médico")
# Criando a partir de sequências de pares
items = [("a", 1), ("b", 2), ("c", 3)]
meu_dict = dict(items)
pessoa = {"nome": "Ana", "idade": 30, "profissao": "Engenheira"}
# Acessando valores
nome = pessoa["nome"] # "Ana"
# Se a chave não existir, gera KeyError
# email = pessoa["email"] # KeyError
# Método seguro para acessar (não gera erro se a chave não existir)
email = pessoa.get("email") # None
email = pessoa.get("email", "não informado") # "não informado" (valor padrão)
# Modificando valores existentes
pessoa["idade"] = 31
# Adicionando novos pares chave-valor
pessoa["email"] = "[email protected]"
# Removendo pares
profissao = pessoa.pop("profissao") # Remove e retorna: "Engenheira"
del pessoa["idade"] # Remove sem retornar
# Limpando o dicionário
pessoa.clear() # {}
pessoa = {"nome": "Ana", "idade": 30, "profissao": "Engenheira"}
# Obter todas as chaves
chaves = pessoa.keys() # dict_keys(['nome', 'idade', 'profissao'])
# Obter todos os valores
valores = pessoa.values() # dict_values(['Ana', 30, 'Engenheira'])
# Obter todos os pares chave-valor como tuplas
itens = pessoa.items() # dict_items([('nome', 'Ana'), ('idade', 30), ('profissao', 'Engenheira')])
# Atualizar o dicionário com outro dicionário
pessoa.update({"email": "[email protected]", "telefone": "123456789"})
# Obter e remover um item, com valor padrão se a chave não existir
hobbie = pessoa.pop("hobbie", "Não informado")
# Obter valor, criando a chave se não existir
endereco = pessoa.setdefault("endereco", "Desconhecido")
pessoa = {"nome": "Ana", "idade": 30, "profissao": "Engenheira"}
# Iterando sobre as chaves (comportamento padrão)
for chave in pessoa:
print(chave, pessoa[chave])
# Iterando sobre os valores
for valor in pessoa.values():
print(valor)
# Iterando sobre pares chave-valor
for chave, valor in pessoa.items():
print(f"{chave}: {valor}")
Dica: Compreensão de Dicionários
Assim como as listas, os dicionários também possuem compreensões:
Conjuntos (Sets)
Conjuntos são coleções não-ordenadas, mutáveis e sem itens duplicados.
# Diferentes formas de criar conjuntos
frutas = {"maçã", "banana", "laranja"}
numeros = {1, 2, 3, 4, 5}
# Duplicatas são automaticamente removidas
letras = {"a", "b", "c", "a", "d", "b"} # {"a", "b", "c", "d"}
# Conjunto vazio (não pode usar {}, que cria um dicionário vazio)
vazio = set()
# Criando a partir de outras sequências
vogais = set("aeiou") # {"a", "e", "i", "o", "u"}
unicos = set([1, 2, 2, 3, 3, 3, 4]) # {1, 2, 3, 4}
# Adicionando elementos
frutas = {"maçã", "banana", "laranja"}
frutas.add("uva") # {"maçã", "banana", "laranja", "uva"}
# Adicionando múltiplos elementos
frutas.update(["pêra", "abacaxi"]) # {"maçã", "banana", "laranja", "uva", "pêra", "abacaxi"}
# Removendo elementos
frutas.remove("banana") # Gera erro se o elemento não existir
frutas.discard("manga") # Não gera erro se o elemento não existir
elemento = frutas.pop() # Remove e retorna um elemento arbitrário
# Limpando o conjunto
frutas.clear() # set()
A = {1, 2, 3, 4, 5}
B = {4, 5, 6, 7, 8}
# União (elementos em A ou B)
union = A | B # ou A.union(B)
# {1, 2, 3, 4, 5, 6, 7, 8}
# Interseção (elementos em A e B)
intersection = A & B # ou A.intersection(B)
# {4, 5}
# Diferença (elementos em A, mas não em B)
difference = A - B # ou A.difference(B)
# {1, 2, 3}
# Diferença simétrica (elementos em A ou B, mas não em ambos)
symmetric_difference = A ^ B # ou A.symmetric_difference(B)
# {1, 2, 3, 6, 7, 8}
A = {1, 2, 3}
B = {1, 2, 3, 4, 5}
C = {1, 2, 3}
# Verificando se um conjunto é subconjunto de outro
print(A.issubset(B)) # True
print(A <= B) # True
# Verificando se um conjunto é superconjunto de outro
print(B.issuperset(A)) # True
print(B >= A) # True
# Verificando igualdade
print(A == C) # True
# Verificando se conjuntos são disjuntos (não têm elementos em comum)
D = {6, 7, 8}
print(A.isdisjoint(D)) # True
Restrições de Conjuntos
- Apenas itens imutáveis (como strings, números e tuplas) podem ser elementos de conjuntos.
- Listas, dicionários e outros conjuntos não podem ser elementos de conjuntos.
- Conjuntos não têm índices, portanto você não pode acessar elementos por posição.
Collections Module
O módulo collections
oferece alternativas e extensões às coleções padrão do Python:
from collections import Counter
# Contando ocorrências de elementos
texto = "mississippi"
contagem = Counter(texto) # Counter({'i': 4, 's': 4, 'p': 2, 'm': 1})
# Elementos mais comuns
mais_comuns = contagem.most_common(2) # [('i', 4), ('s', 4)]
# Operações matemáticas
c1 = Counter("aaabbc")
c2 = Counter("bcccdd")
print(c1 + c2) # Counter({'c': 5, 'b': 3, 'a': 3, 'd': 2})
print(c1 - c2) # Counter({'a': 3, 'b': 1})
from collections import defaultdict
# Dicionário com valor padrão para chaves inexistentes
contagem = defaultdict(int) # Valor padrão: 0
texto = "mississippi"
for letra in texto:
contagem[letra] += 1 # Mesmo para chaves que não existiam antes
print(dict(contagem)) # {'m': 1, 'i': 4, 's': 4, 'p': 2}
# Com outros tipos
lista_padrao = defaultdict(list)
lista_padrao['frutas'].append('maçã') # Não precisa inicializar a lista
from collections import deque
# Fila de duas pontas (double-ended queue)
fila = deque(['a', 'b', 'c'])
# Adicionando elementos
fila.append('d') # ['a', 'b', 'c', 'd']
fila.appendleft('z') # ['z', 'a', 'b', 'c', 'd']
# Removendo elementos
ultimo = fila.pop() # 'd'
primeiro = fila.popleft() # 'z'
# Rotacionando a fila
fila.rotate(1) # Move um lugar para a direita
fila.rotate(-1) # Move um lugar para a esquerda
Escolhendo a Coleção Certa
Cada tipo de coleção tem suas próprias características e casos de uso ideais:
Quando usar cada coleção
- Listas: Quando a ordem é importante e os elementos podem mudar
- Tuplas: Para dados fixos, imutáveis e/ou heterogêneos
- Dicionários: Quando você precisa associar valores a chaves para acesso rápido
- Conjuntos: Quando você precisa garantir elementos únicos ou realizar operações de conjuntos
# Lista: Coleção ordenada de itens similares
tarefas = ["Estudar Python", "Fazer exercícios", "Revisar código"]
# Tupla: Representando estruturas fixas, como coordenadas
ponto = (10, 20, 30) # x, y, z
# Dicionário: Armazenando informações relacionadas
aluno = {
"nome": "Maria",
"idade": 22,
"curso": "Ciência da Computação",
"notas": [9.5, 8.0, 7.5]
}
# Conjunto: Removendo duplicatas e verificando pertinência
tags = {"python", "programação", "código", "python"} # Duplicata removida
tem_java = "java" in tags # Verificação rápida: False
Resumo
Nesta aula, você aprendeu sobre:
- Listas: Coleções ordenadas e mutáveis
- Tuplas: Coleções ordenadas e imutáveis
- Dicionários: Coleções de pares chave-valor, mutáveis e com chaves únicas
- Conjuntos: Coleções de elementos únicos, não-ordenadas e mutáveis
- Módulo Collections: Coleções especializadas como Counter, defaultdict e namedtuple
- Operações e métodos específicos para cada tipo de coleção
- Compreensões para criar listas e dicionários de forma concisa
Recursos de aprendizado
Próximos Passos
Na próxima aula, exploraremos funções em Python, que nos permitem organizar código em blocos reutilizáveis.