Compreensões
Compreensões em Python são construções sintáticas concisas para criar listas, dicionários, conjuntos e geradores a partir de iteráveis. Esta aula aborda list, dict e set comprehensions, generator expressions, aninhamento e boas práticas de legibilidade.
Compreensões (comprehensions) são uma característica poderosa e elegante da linguagem Python que permite criar sequências de forma concisa e expressiva. Elas substituem loops tradicionais de forma mais legível e, muitas vezes, mais eficiente. Nesta aula, exploraremos comprehensions para listas, dicionários e conjuntos, além das expressões geradoras, que são uma variação econômica em termos de memória. Também veremos como aninhar comprehensions e discutiremos quando usá-las para manter o código claro.
Dominar comprehensions é essencial para escrever código Python idiomático. Elas estão presentes em todo o ecossistema Python, desde scripts simples até grandes frameworks. Ao final desta aula, você será capaz de substituir vários padrões de loop por comprehensions elegantes.
List, dict e set comprehensions
List comprehension é a forma mais comum. Sua sintaxe básica é: [expressão for item in iterável if condição]. Ela cria uma nova lista aplicando a expressão a cada item do iterável que satisfizer a condição (opcional).
Exemplo prático: gerar uma lista de quadrados dos números pares de 0 a 9.
quadrados_pares = [x**2 for x in range(10) if x % 2 == 0]
print(quadrados_pares) # [0, 4, 16, 36, 64]Dict comprehension segue a mesma ideia, mas gera um dicionário. Sintaxe: {chave: valor for item in iterável if condição}.
Exemplo: mapear números de 0 a 4 para seus cubos.
cubos = {x: x**3 for x in range(5)}
print(cubos) # {0: 0, 1: 1, 2: 8, 3: 27, 4: 64}Set comprehension cria um conjunto (set) sem elementos duplicados. Sintaxe: {expressão for item in iterável if condição}. Note que usa chaves como dict, mas sem os dois pontos.
Exemplo: extrair as primeiras letras de uma lista de palavras, removendo duplicatas.
palavras = ['apple', 'banana', 'avocado', 'blueberry']
primeiras = {palavra[0] for palavra in palavras}
print(primeiras) # {'a', 'b'}Todas as comprehensions podem conter múltiplos for e if (aninhamento), como veremos adiante.
Generator expressions
Generator expressions são semelhantes a list comprehensions, mas usam parênteses em vez de colchetes e produzem um objeto gerador, que é lazy: os elementos são gerados um por vez sob demanda, economizando memória. Sintaxe: (expressão for item in iterável if condição).
Exemplo: calcular a soma dos quadrados dos números de 1 a 1000000.
soma = sum(x**2 for x in range(1, 1000001))
print(soma) # 333333833333500000Se usássemos uma list comprehension, uma lista gigante seria criada na memória. Com generator expression, apenas um valor de cada vez é processado.
Outro uso comum é passar uma generator expression diretamente para funções como sum(), min(), max(), any(), all(). Note que os parênteses da função podem ser os mesmos da expressão, dispensando parênteses extras.
# Verificar se todos os números são pares
todos_pares = all(x % 2 == 0 for x in range(0, 10, 2))
print(todos_pares) # TrueAninhamento
Comprehensions podem conter múltiplos loops aninhados, que funcionam como loops for aninhados na mesma ordem. Por exemplo, para gerar pares (i, j) de duas listas:
pares = [(i, j) for i in range(3) for j in range(2)]
print(pares) # [(0,0), (0,1), (1,0), (1,1), (2,0), (2,1)]Também é possível aninhar comprehensions dentro de comprehensions (como uma lista de listas). Exemplo: matriz transposta.
matriz = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
transposta = [[linha[i] for linha in matriz] for i in range(3)]
print(transposta) # [[1, 4, 7], [2, 5, 8], [3, 6, 9]]No entanto, cuidado com o excesso de aninhamento: mais de dois ou três níveis pode prejudicar a legibilidade. Nesses casos, considere usar loops tradicionais ou funções auxiliares.
Legibilidade
Comprehensions são geralmente mais legíveis que loops equivalentes, desde que não fiquem muito longas ou complexas. Aqui estão algumas boas práticas:
- Mantenha a expressão simples: evite efeitos colaterais (como chamadas de função que alteram estado).
- Limite o número de cláusulas: se precisar de mais de dois
forouif, avalie se um loop explícito não seria mais claro. - Use nomes descritivos: para variáveis dentro da comprehension.
- Preferir generator expressions a list comprehensions quando não precisar armazenar todos os resultados (por exemplo, em funções como
sum()).
Exemplo de código difícil de ler:
# Ruim: aninhamento excessivo
result = [[x for x in range(y) if x % 2 == 0] for y in range(5) if y > 2]Melhor separar em etapas ou usar loops:
result = []
for y in range(5):
if y > 2:
result.append([x for x in range(y) if x % 2 == 0])Em geral, se uma comprehension ultrapassa 80 caracteres, quebre em múltiplas linhas com indentação adequada.
Referências
- Python Tutorial: List Comprehensions
- Python Reference: Generator Expressions
- Python Docs: Dict Comprehensions
- Python Docs: Set Comprehensions
- Real Python: List Comprehension in Python
- PEP 289 – Generator Expressions
Exercícios
Crie uma list comprehension que gere uma lista dos cubos dos números ímpares de 1 a 20.
✓ Resposta:cubos_impares = [x**3 for x in range(1, 21) if x % 2 != 0] print(cubos_impares)Dada a lista de strings
frutas = ['maçã', 'banana', 'abacaxi', 'laranja'], use dict comprehension para criar um dicionário onde a chave é a fruta e o valor é o número de vogais (a, e, i, o, u) na palavra.✓ Resposta:frutas = ['maçã', 'banana', 'abacaxi', 'laranja'] contagem_vogais = {fruta: sum(1 for letra in fruta if letra.lower() in 'aeiou') for fruta in frutas} print(contagem_vogais)Use set comprehension para encontrar os caracteres únicos que aparecem em todas as palavras da lista
['casa', 'carro', 'cachorro'](interseção de conjuntos).✓ Resposta:palavras = ['casa', 'carro', 'cachorro'] # Usando set.intersection com generator expression comuns = set.intersection(*(set(palavra) for palavra in palavras)) print(comuns) # {'a', 'c', 'r'} # Alternativa com loop: # comuns = {letra for letra in palavras[0] if all(letra in p for p in palavras[1:])}Dada uma lista de números
nums = [1, 2, 3, 4, 5, 6], use uma generator expression para calcular o produto de todos os números pares (usemath.prodou loop).✓ Resposta:import math nums = [1, 2, 3, 4, 5, 6] produto_pares = math.prod(x for x in nums if x % 2 == 0) print(produto_pares) # 48 (2*4*6)Crie uma lista de listas (matriz 3x3) usando list comprehension aninhada, onde cada elemento é a soma dos índices de linha e coluna (i+j).
✓ Resposta:matriz = [[i+j for j in range(3)] for i in range(3)] print(matriz) # [[0,1,2],[1,2,3],[2,3,4]]