Comprehensions & Expressões Geradoras
Comprehensions constroem listas, dicionários e conjuntos a partir de iteráveis em uma única expressão. Expressões geradoras se parecem com isso, mas retornam um iterador preguiçoso - ideal para pipelines que nunca precisam da coleção completa na memória.
Receita
squares = [n * n for n in range(10)]
evens = {n for n in range(20) if n % 2 == 0}
index = {name: i for i, name in enumerate(["ada", "linus"])}
total = sum(x * x for x in range(100_000)) # generator - no big listQuando usar isso:
- Transformar ou filtrar sequências de forma declarativa
- Construir dicionários de consulta a partir de iteráveis paralelos
- Transmitir grandes conjuntos de dados através de
sum/any/all/max - Substituir loops de append de três linhas por uma única expressão
Exemplo de Trabalho
from pathlib import Path
def load_word_counts(paths: list[Path]) -> dict[str, int]:
words = (
word.lower()
for path in paths
for line in path.read_text(encoding="utf-8").splitlines()
for word in line.split()
)
return {word: len(word) for word in sorted(set(words))}
def active_user_emails(rows: list[dict[str, object]]) -> list[str]:
return [
str(row["email"])
for row in rows
if row.get("active") and "email" in row
]
def chunk_indices(size: int, chunk: int) -> list[tuple[int, int]]:
return [(i, min(i + chunk, size)) for i in range(0, size, chunk)]
if __name__ == "__main__":
print(active_user_emails([
{"email": "a@x.com", "active": True},
{"email": "b@x.com", "active": False},
]))
print(chunk_indices(10, 3))O que isso demonstra:
- Expressão geradora aninhada achata arquivos sem listas intermediárias
- Comprehension de lista filtra e projeta linhas de dicionário
- Comprehension de conjunto dentro da comp de dicionário remove duplicatas de palavras antes do mapeamento de comprimento
- Argumento gerador para
sumevita alocar 100k inteiros
Mergulho Profundo
Como Funciona
- Comprehensions Eager (Ansiosas) - Comps de lista/dicionário/conjunto constroem a coleção completa imediatamente.
- Expressões Geradoras - Entre parênteses
(x for x in it)retornam um objeto gerador. - Expressão Única - Sem declarações dentro de comps - apenas expressões e filtros
if. - Escopo - Comprehensions têm seu próprio escopo local no Python 3 (variáveis de loop não vazam).
- Encadeamento - Múltiplas cláusulas
foraninham da esquerda para a direita como loops aninhados.
Quando Escolher Qual
| Forma | Memória | Reutilização |
|---|---|---|
Comp de lista [...] | Armazena todos os itens | Sim - acesso aleatório |
Comp de conjunto {...} | Armazena itens únicos | Sim |
Comp de dicionário {k: v ...} | Armazena todos os pares | Sim |
Gerador (...) | Estado do iterador O(1) | Consumir uma vez |
Notas Python
# Walrus in comprehension (3.8+)
filtered = [y for x in data if (y := transform(x)) is not None]
# dict.fromkeys for simple key initialization
unique_order = list(dict.fromkeys(items)) # preserve order, dedupeArmadilhas
- Efeitos colaterais em comps -
[print(x) for x in itens]constrói uma lista de None. Correção: Use um loopforsimples para efeitos. - Comp de lista enorme -
[processar(x) for x in bilhao_de_linhas]esgota a RAM. Correção: Gerador e processamento em stream. - Aninhamento ilegível - Três cláusulas
forem uma linha obscurecem a intenção. Correção: Divida em funções auxiliares ou useitertools. - Colisão de chaves em comp de dicionário - Chaves posteriores sobrescrevem as anteriores silenciosamente. Correção: Valide a unicidade ou use um loop com verificações.
- Gerador esgotado - Iterar duas vezes não retorna nada na segunda vez. Correção: Materialize para lista ou recrie o gerador.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
| Expressão geradora | Streams grandes ou infinitos | Precisa de indexação ou len() |
Loop for | Efeitos colaterais, ramificação complexa | Simples map/filter |
map/filter | Estilo funcional com funções | Múltiplas cláusulas if/for |
itertools | Janelas deslizantes, encadeamento | Comp simples de uma linha |
FAQs
Posso usar else em uma comprehension?
Sim: [x if x > 0 else 0 for x in nums] - expressão antes de for, não o mesmo que else de loop.
Comprehensions são mais rápidas que loops?
Frequentemente sim em CPython - bytecode otimizado e sem busca repetida de métodos para append.
Quando devo usar um gerador?
Quando os dados não cabem na memória ou você passa apenas uma vez para funções de agregação.
Variáveis de comprehension vazam?
Não no Python 3 - x em [x for x in itens] é local à comprehension.
Como achatar uma lista aninhada?
[y for linha in matriz for y in linha] - múltiplas cláusulas for achatam um nível.
Posso construir um dicionário a partir de duas listas?
{k: v for k, v in zip(chaves, valores)} - ou dict(zip(chaves, valores)) quando nenhum filtro é necessário.
O que é uma comprehension de conjunto?
{expr for x in itens} - chaves sem dois pontos. Produz um conjunto, não um dicionário.
Devo atribuir um gerador a uma variável?
Sim, ao reutilizar a definição do pipeline: gen = (x for x in dados if pred(x)), então passe para funções.
Como depurar uma comp complexa?
Expanda temporariamente para um loop for, ou extraia a expressão interna para uma função nomeada.
List(map(...)) está obsoleto?
Nem sempre - map com uma função existente pode ser mais claro. Comprehensions ganham para transformações inline com filtros.
Relacionados
- Geradores & yield - funções geradoras completas
- itertools - composição avançada de iteradores
- Listas & Tuplas - operações de lista
- Fluxo de Controle - quando loops superam comps
Versões do Stack: Esta página foi escrita para Python 3.14.0 (stable 3.14, maintenance 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, e uv 0.6+.