Comparação de Containers e Comprehensions Abrangentes

Cobrimos listas, tuplas, dicionários e conjuntos individualmente. Agora vamos fazer uma comparação lado a lado — quais são as diferenças, e quando você deve usar cada um? Também dominaremos completamente as comprehensions, um dos recursos mais poderosos do Python.


1. Quatro Containers Comparados

Característica Lista (list) Tupla (tuple) Dicionário (dict) Conjunto (set)
Sintaxe [] () {chave: valor} {} ou set()
Ordenado ✅ Sim ✅ Sim ✅ Ordem de inserção (3.7+) ❌ Não ordenado
Mutável
Duplicatas ✅ Permitidas ✅ Permitidas Chaves únicas, valores podem repetir ❌ Elementos únicos
Acesso Índice [0] Índice [0] Chave ["chave"] Sem suporte a índice
Velocidade de busca O(n) lenta O(n) lenta O(1) muito rápida O(1) muito rápida
Uso típico Dados ordenados, coleções dinâmicas Dados fixos, retornos de função Mapeamentos, caches Dedup, operações de conjunto
💡 Princípios-chave de seleção: 1) Precisa de acesso por posição → lista/tupla; 2) Precisa de acesso por nome → dicionário; 3) Precisa de dedup ou operações matemáticas → conjunto; 4) Dados não devem mudar → tupla.

Exemplo: Comparação de Seleção de Container (Dificuldade ⭐⭐)

PYTHON
# Mesmo cenário implementado com diferentes containers

# Cenário: armazenar nomes de alunos
# Lista — ordenada, fácil de adicionar/remover
students_list = ["Alice", "Bob", "Charlie"]
students_list.append("Diana")
print(f"Lista: {students_list[0]}")    # Alice

# Tupla — fixa (como uma lista de chamada)
students_tuple = ("Alice", "Bob", "Charlie")
# students_tuple[0] = "xxx"     # Erro! Tuplas são imutáveis
print(f"Tupla: {students_tuple[0]}")   # Alice

# Dicionário — busca rápida por ID
students_dict = {
    "001": "Alice",
    "002": "Bob",
    "003": "Charlie",
}
print(f"Dict: {students_dict['002']}")  # Bob — velocidade O(1)

# Conjunto — deduplicação (como uma lista de presença)
attendance = {"Alice", "Bob", "Charlie", "Alice"}
print(f"Set: {attendance}")            # {'Bob', 'Charlie', 'Alice'} — Alice deduplicada
▶ Experimente

2. List Comprehensions Avançadas

A Lição 11 cobriu comprehensions básicas. Vamos nos aprofundar.

Múltiplas Condições

PYTHON
numbers = range(1, 31)

# Divisível por 3 E por 5
filtered = [n for n in numbers if n % 3 == 0 and n % 5 == 0]
print(filtered)             # [15, 30]

# Divisível por 3 OU por 5
filtered = [n for n in numbers if n % 3 == 0 or n % 5 == 0]
print(filtered)             # [3, 5, 6, 9, 10, 12, 15, 18, 20, 21, 24, 25, 27, 30]

Comprehensions com Laços Aninhados

PYTHON
# Gera pares de coordenadas — equivalente a laço for duplo
pairs = [(x, y) for x in range(3) for y in range(3)]
print(pairs)
# [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]

# Aninhado com condição — encontra pares onde a soma é par
pairs = [(x, y) for x in range(3) for y in range(3) if (x + y) % 2 == 0]
print(pairs)
# [(0, 0), (0, 2), (1, 1), (2, 0), (2, 2)]

if-else em Comprehensions

PYTHON
# if-else em comprehensions — observe a posição diferente
numbers = [1, 2, 3, 4, 5, 6]

# Apenas if (filtragem) — colocado depois
evens = [n for n in numbers if n % 2 == 0]

# if-else (transformação) — colocado antes
result = ["par" if n % 2 == 0 else "ímpar" for n in numbers]
print(result)   # ['ímpar', 'par', 'ímpar', 'par', 'ímpar', 'par']

Exemplo: Pipeline de Transformação de Dados (Dificuldade ⭐⭐⭐)

PYTHON
# Uma linha: filtrar → transformar → formatar
raw = ["  maçã  ", "BANANA", "", "  CEREJA", None, "  tâmara  "]

# Filtra None e strings vazias → remove espaços → capitaliza
cleaned = [item.strip().capitalize() for item in raw if item and item.strip()]
print(cleaned)              # ['Maçã', 'Banana', 'Cereja', 'Tâmara']
▶ Experimente

Saída:

TEXT
['Maçã', 'Banana', 'Cereja', 'Tâmara']

3. Dict Comprehensions

Dicionários também podem usar comprehensions. A sintaxe é similar à de listas, mas usa {} e especifica pares chave-valor:

PYTHON
# Dict comprehension básica
squares = {x: x ** 2 for x in range(5)}
print(squares)              # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

# Com condição
even_squares = {x: x ** 2 for x in range(10) if x % 2 == 0}
print(even_squares)         # {0: 0, 2: 4, 4: 16, 6: 36, 8: 64}

# Inverter chaves e valores
original = {"a": 1, "b": 2, "c": 3}
reversed_dict = {value: key for key, value in original.items()}
print(reversed_dict)        # {1: 'a', 2: 'b', 3: 'c'}

Prático: Mesclar Duas Listas em um Dict

PYTHON
# Mescla duas listas em um dicionário
names = ["Alice", "Bob", "Charlie"]
scores = [85, 92, 78]
result = {names[i]: scores[i] for i in range(len(names))}
print(result)               # {'Alice': 85, 'Bob': 92, 'Charlie': 78}

# Usando zip() é mais elegante
result = {name: score for name, score in zip(names, scores)}
print(result)               # {'Alice': 85, 'Bob': 92, 'Charlie': 78}

4. Set Comprehensions

Set comprehensions usam {} com apenas uma expressão (sem dois pontos) — a diferença de dict comprehensions é a presença ou ausência de dois pontos:

PYTHON
# Set comprehension — auto-deduplicação
numbers = [1, 2, 2, 3, 3, 3, 4, 5, 5]
unique_squares = {x ** 2 for x in numbers}
print(unique_squares)       # {1, 4, 9, 16, 25}

# Com condição
even_set = {x for x in range(20) if x % 2 == 0}
print(even_set)             # {0, 2, 4, 6, 8, 10, 12, 14, 16, 18}
💡 As três distinções: [x for x in ...] é uma lista — ordenada, duplicatas permitidas. {x: y for x in ...} é um dict — tem dois pontos. {x for x in ...} é um set — sem dois pontos, não ordenado, deduplicado.

Exemplo: Análise de Vocabulário (Dificuldade ⭐⭐⭐)

PYTHON
# Analisa vocabulário em um artigo
article = """
Python é ótimo. Python é poderoso!
Eu amo Python. JavaScript também é ótimo.
Mas Python é meu favorito.
"""

# Extrai todas as palavras
words = article.lower().split()

# Deduplica com set comprehension
unique_words = {word.strip(".!,") for word in words}
print(f"Total de palavras: {len(words)}")
print(f"Palavras únicas: {len(unique_words)}")
print(f"Todas as palavras únicas: {sorted(unique_words)}")
▶ Experimente

Saída:

TEXT
Total de palavras: 18
Palavras únicas: 10
Todas as palavras únicas: ['é', 'amo', 'favorito', 'javascript', 'mas', 'meu', 'ótimo', 'pod eroso', 'python', 'também']

Casos de Uso Comuns


❓ Perguntas Frequentes

P: Qual a diferença entre list comprehensions e expressões geradoras? R: List comprehensions [x for x in range(10)] geram todos os dados de uma vez na memória. Expressões geradoras (x for x in range(10)) são preguiçosas — um valor de cada vez, economizando memória. Use geradores para grandes conjuntos de dados (dezenas de milhares+). ⚠️ P: E se uma comprehension tiver mais de dois níveis de aninhamento? R: Comprehensions com mais de dois níveis se tornam ilegíveis. Código como [x for xs in matrix for ys in xs for x in ys] é quase impossível de entender rapidamente. Se você precisar de três+ níveis, use laços for regulares ou funções auxiliares. P: Como decido qual container usar? R: Três perguntas: ① Precisa de chaves únicas? → dicionário. ② Precisa de dedup ou operações de conjunto? → set. ③ Os dados precisam mudar? → lista se sim, tupla se não. Na maioria dos cenários, listas e dicionários cobrem 90% dos casos de uso.


📖 Resumo


📝 Atividades

  1. Básico (Dificuldade ⭐): Use uma list comprehension para gerar todos os números entre 10 e 50 que são divisíveis por 7 ou contêm o dígito 7. Dica: Use or para combinar duas condições.

  2. Intermediário (Dificuldade ⭐⭐): Dadas duas listas keys = ["name", "age", "city"] e values = ["Alice", 25, "São Paulo"], use uma dict comprehension para mesclá-las em um dict. Dica: Use zip(keys, values) para pareá-las.

  3. Desafio (Dificuldade ⭐⭐⭐): Escreva um "analisador de dados." Dada uma string contendo múltiplas sentenças, conte e exiba: total de palavras, número de palavras únicas e as 3 palavras mais frequentes. Dica: Use split() para tokenização, um dicionário para contagem, e sorted(dict.items(), key=lambda x: x[1], reverse=True)[:3] para o top 3.

100%