34. Comprehensions: Uma Forma Compacta de Criar Listas, Dicionários e Conjuntos
Comprehensions são uma das funcionalidades mais elegantes do Python, permitindo que você crie e transforme coleções em uma única linha de código legível. Em vez de escrever várias linhas com loops e operações de append, comprehensions deixam você expressar a mesma lógica de forma mais concisa e, muitas vezes, mais clara.
Neste capítulo, vamos explorar como usar list comprehensions, dictionary comprehensions e set comprehensions para escrever código mais Pythonic. Vamos ver como incorporar lógica condicional, quando escolher comprehensions em vez de loops tradicionais e como lidar com cenários mais complexos com iterações aninhadas.
34.1) List Comprehensions para Criar e Transformar Listas
34.1.1) A Sintaxe Básica de List Comprehension
Uma list comprehension fornece uma forma compacta de criar uma nova lista aplicando uma expressão a cada item em uma sequência existente. A sintaxe básica é:
[expression for item in iterable]Isso cria uma nova lista em que cada elemento é o resultado de avaliar expression para cada item no iterable (qualquer sequência sobre a qual você pode iterar, como uma lista, range ou string).
Vamos começar com um exemplo simples. Suponha que queremos criar uma lista de quadrados para números de 0 a 4:
# Abordagem tradicional com um loop
squares = []
for number in range(5):
squares.append(number ** 2)
print(squares) # Output: [0, 1, 4, 9, 16]Com uma list comprehension, podemos expressar isso de forma mais concisa:
# Usando uma list comprehension
squares = [number ** 2 for number in range(5)]
print(squares) # Output: [0, 1, 4, 9, 16]As duas abordagens produzem o mesmo resultado, mas a comprehension é mais compacta e, quando você se familiariza com a sintaxe, muitas vezes é mais fácil de ler. A comprehension mostra claramente que estamos criando uma lista de valores ao quadrado.
34.1.2) Transformando Dados Existentes
List comprehensions se destacam em transformar dados de uma forma para outra. Vamos ver alguns exemplos práticos.
Convertendo temperaturas de Celsius para Fahrenheit:
# Dados de temperatura em Celsius
celsius_temps = [0, 10, 20, 30, 40]
# Converter para Fahrenheit usando a fórmula: F = C * 9/5 + 32
fahrenheit_temps = [temp * 9/5 + 32 for temp in celsius_temps]
print(fahrenheit_temps) # Output: [32.0, 50.0, 68.0, 86.0, 104.0]Convertendo strings para maiúsculas:
# Códigos de produto em caixa mista
product_codes = ["abc123", "def456", "ghi789"]
# Padronizar para maiúsculas
uppercase_codes = [code.upper() for code in product_codes]
print(uppercase_codes) # Output: ['ABC123', 'DEF456', 'GHI789']34.1.3) Criando Listas a Partir de Objetos Range
List comprehensions funcionam naturalmente com range(), que aprendemos no Capítulo 12. Isso é útil para gerar sequências com padrões específicos:
# Gerar números pares de 0 a 10
evens = [n * 2 for n in range(6)] # n vai de 0 a 5, então n*2 dá 0, 2, 4, 6, 8, 10
print(evens) # Output: [0, 2, 4, 6, 8, 10]
# Gerar múltiplos de 5
multiples_of_five = [n * 5 for n in range(1, 6)]
print(multiples_of_five) # Output: [5, 10, 15, 20, 25]34.1.4) Comprehensions vs Construir Listas com Append
É importante entender que list comprehensions criam a lista inteira em uma operação, enquanto a abordagem tradicional com loop constrói a lista incrementalmente. Ambas produzem o mesmo resultado, mas comprehensions geralmente são mais rápidas para criar novas listas e são consideradas mais Pythonic.
Aqui vai uma comparação lado a lado:
# Abordagem tradicional com loop
result = []
for i in range(5):
result.append(i * 3)
print(result) # Output: [0, 3, 6, 9, 12]
# Abordagem com list comprehension
result = [i * 3 for i in range(5)]
print(result) # Output: [0, 3, 6, 9, 12]As duas abordagens são válidas, mas a comprehension é mais concisa e expressa claramente a intenção: "crie uma lista de valores em que cada valor é i * 3".
34.2) Lógica Condicional Dentro de List Comprehensions
34.2.1) Filtrando com Condições if
Uma das funcionalidades mais poderosas de list comprehensions é a capacidade de filtrar itens com base em uma condição. Você pode adicionar uma cláusula if no final da comprehension para incluir apenas itens que atendem a certos critérios:
[expression for item in iterable if condition]A cláusula if atua como um filtro: o Python avalia a condição para cada item, e apenas itens para os quais a condição é True serão incluídos na lista resultante. Itens que não atendem à condição são pulados completamente.
Vamos ver isso na prática com um exemplo simples:
# Obter apenas números pares de 0 a 9
numbers = range(10)
evens = [n for n in numbers if n % 2 == 0]
print(evens) # Output: [0, 2, 4, 6, 8]Aqui, n % 2 == 0 verifica se um número é par. Apenas números que passam nesse teste são incluídos na nova lista.
Filtrando notas de alunos:
# Notas de prova dos alunos
scores = [45, 78, 92, 65, 88, 55, 73, 95]
# Obter apenas notas de aprovação (>= 70)
passing_scores = [score for score in scores if score >= 70]
print(passing_scores) # Output: [78, 92, 88, 73, 95]34.2.2) Transformando Itens Filtrados
Você pode combinar filtragem com transformação aplicando uma expressão aos itens filtrados:
# Notas dos alunos
scores = [45, 78, 92, 65, 88, 55, 73, 95]
# Obter notas de aprovação e escalá-las para a faixa 0-10
scaled_passing = [score / 10 for score in scores if score >= 70]
print(scaled_passing) # Output: [7.8, 9.2, 8.8, 7.3, 9.5]
# Primeiro filtra (mantém apenas >= 70), depois transforma (divide por 10)Convertendo e filtrando strings:
# Nomes de produtos com qualidade mista
products = ["apple", "BANANA", "cherry", "DATE", "elderberry"]
# Obter versões em maiúsculas de produtos com nomes maiores que 5 caracteres
long_products_upper = [product.upper() for product in products if len(product) > 5]
print(long_products_upper) # Output: ['BANANA', 'CHERRY', 'ELDERBERRY']34.2.3) Usando Expressões Condicionais (if-else) em Comprehensions
Às vezes você quer transformar itens de forma diferente com base em uma condição, em vez de filtrá-los. Para isso, você usa uma expressão condicional (conditional expression) (que aprendemos no Capítulo 10) na parte de expressão da compreensão (comprehension):
[expression_if_true if condition else expression_if_false for item in iterable]Isso é diferente de filtragem. Aqui, todo item é incluído no resultado — o if-else determina qual expressão aplicar a cada item. A expressão condicional (do Capítulo 10) aparece na parte da expressão, antes da cláusula for.
Note a diferença de sintaxe:
- Filtragem:
[expr for item in seq if condition]-ifno final, semelse - Expressão condicional:
[expr_if if cond else expr_else for item in seq]-if-elsena expressão, antes dofor
# Classificar números como par ou ímpar
numbers = range(6)
classifications = ["even" if n % 2 == 0 else "odd" for n in numbers]
print(classifications) # Output: ['even', 'odd', 'even', 'odd', 'even', 'odd']Aplicando transformações diferentes com base em condições:
# Notas dos alunos
scores = [45, 78, 92, 65, 88, 55, 73, 95]
# Adicionar pontos de bônus a notas de reprovação, manter notas de aprovação como estão
adjusted_scores = [score + 10 if score < 70 else score for score in scores]
print(adjusted_scores) # Output: [55, 78, 92, 75, 88, 65, 73, 95]Em ambos os exemplos, note:
- Todo item da lista original aparece no resultado
- O
if-elsedetermina em que valor cada item se transforma - Nenhum item é filtrado
34.2.4) Entendendo a Diferença: Filtragem vs Expressão Condicional
É crucial entender a diferença entre esses dois padrões:
Filtragem (if no final) - Alguns itens são excluídos:
# Incluir apenas números positivos
numbers = [-2, 5, -1, 8, 0, 3]
positives = [n for n in numbers if n > 0]
print(positives) # Output: [5, 8, 3]
print(len(positives)) # Output: 3 (somente 3 itens)
# Processo: Verificar condição → Se True, incluir item → Se False, pular itemExpressão condicional (if-else na expressão) - Todos os itens são incluídos, mas transformados de forma diferente:
# Converter números negativos para zero, manter números positivos
numbers = [-2, 5, -1, 8, 0, 3]
non_negatives = [n if n > 0 else 0 for n in numbers]
print(non_negatives) # Output: [0, 5, 0, 8, 0, 3]
print(len(non_negatives)) # Output: 6 (todos os 6 itens)
# Processo: Verificar condição → Se True, usar a primeira expr → Se False, usar a segunda expr → Sempre incluir o resultado34.3) Dictionary Comprehensions
34.3.1) Sintaxe Básica de Dictionary Comprehension
Assim como list comprehensions criam listas, dictionary comprehensions criam dicionários (tipo dict). A sintaxe é parecida, mas você especifica tanto uma chave quanto um valor:
{key_expression: value_expression for item in iterable}Isso cria um novo dicionário em que cada par chave-valor é gerado a partir do iterável.
Vamos começar com um exemplo simples que cria um dicionário mapeando números para seus quadrados:
# Criar um dicionário de números e seus quadrados
squares_dict = {n: n ** 2 for n in range(5)}
print(squares_dict) # Output: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}Criando um dicionário a partir de duas listas:
# Nomes dos alunos e suas notas
names = ["Alice", "Bob", "Charlie"]
scores = [85, 92, 78]
# Criar um dicionário mapeando nomes para notas
student_scores = {names[i]: scores[i] for i in range(len(names))}
print(student_scores) # Output: {'Alice': 85, 'Bob': 92, 'Charlie': 78}Uma forma mais elegante de combinar duas sequências é usando zip(), que vamos aprender no Capítulo 37. Por enquanto, a abordagem baseada em índice funciona bem.
34.3.2) Transformando Dicionários Existentes
Dictionary comprehensions são excelentes para transformar dicionários existentes. Você pode modificar chaves, valores ou ambos.
Ao iterar sobre um dicionário em uma comprehension, use .items() para acessar tanto as chaves quanto os valores. O método .items() retorna pares chave-valor que você pode desempacotar na cláusula for:
# Preços originais em dólares
prices = {"apple": 1.50, "banana": 0.75, "cherry": 2.00}
# Converter para centavos (multiplicar por 100)
prices_in_cents = {fruit: price * 100 for fruit, price in prices.items()}
print(prices_in_cents) # Output: {'apple': 150.0, 'banana': 75.0, 'cherry': 200.0}Transformando chaves:
# Códigos de produto em minúsculas
codes = {"abc": 100, "def": 200, "ghi": 300}
# Converter chaves para maiúsculas
uppercase_codes = {code.upper(): quantity for code, quantity in codes.items()}
print(uppercase_codes) # Output: {'ABC': 100, 'DEF': 200, 'GHI': 300}Transformando tanto chaves quanto valores:
# Nomes dos alunos e notas
scores = {"alice": 85, "bob": 92, "charlie": 78}
# Capitalizar nomes e escalar notas para a faixa 0-10
formatted_scores = {name.capitalize(): score / 10 for name, score in scores.items()}
print(formatted_scores) # Output: {'Alice': 8.5, 'Bob': 9.2, 'Charlie': 7.8}34.3.3) Filtrando Itens do Dicionário
Assim como list comprehensions, dictionary comprehensions podem incluir condições para filtrar itens:
# Notas dos alunos
scores = {"Alice": 85, "Bob": 65, "Charlie": 92, "David": 55, "Eve": 78}
# Obter apenas notas de aprovação (>= 70)
passing_scores = {name: score for name, score in scores.items() if score >= 70}
print(passing_scores) # Output: {'Alice': 85, 'Charlie': 92, 'Eve': 78}Filtrando por características da chave:
# Inventário de produtos
inventory = {"apple": 50, "banana": 30, "apricot": 20, "cherry": 40}
# Obter apenas produtos que começam com 'a'
a_products = {product: quantity for product, quantity in inventory.items()
if product.startswith('a')}
print(a_products) # Output: {'apple': 50, 'apricot': 20}34.3.4) Criando Dicionários a Partir de Sequências
Dictionary comprehensions são úteis para criar dicionários de lookup a partir de sequências:
# Lista de palavras
words = ["python", "java", "ruby", "javascript"]
# Criar um dicionário mapeando cada palavra para seu tamanho
word_lengths = {word: len(word) for word in words}
print(word_lengths) # Output: {'python': 6, 'java': 4, 'ruby': 4, 'javascript': 10}34.3.5) Usando Expressões Condicionais em Dictionary Comprehensions
Você pode usar expressões condicionais para calcular valores de forma diferente com base em condições:
# Notas dos alunos
scores = {"Alice": 85, "Bob": 65, "Charlie": 92, "David": 55}
# Adicionar status "Pass" ou "Fail"
scores_with_status = {name: "Pass" if score >= 70 else "Fail"
for name, score in scores.items()}
print(scores_with_status) # Output: {'Alice': 'Pass', 'Bob': 'Fail', 'Charlie': 'Pass', 'David': 'Fail'}Aplicando transformações diferentes:
# Preços de produtos
prices = {"apple": 1.50, "banana": 0.75, "cherry": 2.50}
# Aplicar desconto a itens caros (> $2.00)
discounted_prices = {product: price * 0.9 if price > 2.00 else price
for product, price in prices.items()}
print(discounted_prices) # Output: {'apple': 1.5, 'banana': 0.75, 'cherry': 2.25}34.4) Set Comprehensions
34.4.1) Sintaxe Básica de Set Comprehension
Set comprehensions criam conjuntos (tipo set) usando uma sintaxe parecida com list comprehensions, mas com chaves:
{expression for item in iterable}O resultado é um conjunto, o que significa que valores duplicados são removidos automaticamente e a ordem não é garantida.
# Criar um conjunto de quadrados
squares_set = {n ** 2 for n in range(6)}
print(squares_set) # Output: {0, 1, 4, 9, 16, 25}A diferença-chave em relação a list comprehensions é que conjuntos eliminam duplicatas automaticamente:
# List comprehension - mantém duplicatas
numbers = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
squared_list = [n ** 2 for n in numbers]
print(squared_list) # Output: [1, 4, 4, 9, 9, 9, 16, 16, 16, 16]
# Set comprehension - remove duplicatas
squared_set = {n ** 2 for n in numbers}
print(squared_set) # Output: {16, 1, 4, 9} (a ordem pode variar)Note que a ordem da saída do conjunto pode ser diferente do que você vê aqui. Conjuntos são coleções sem ordenação, então o Python pode exibir os elementos em qualquer ordem.
34.4.2) Extraindo Valores Únicos
Set comprehensions são perfeitas quando você precisa extrair valores únicos de uma coleção:
# Respostas dos alunos (com duplicatas)
responses = ["yes", "no", "yes", "maybe", "no", "yes", "maybe"]
# Obter respostas únicas
unique_responses = {response for response in responses}
print(unique_responses) # Output: {'maybe', 'yes', 'no'}Extraindo caracteres únicos de strings:
# Texto com caracteres repetidos
text = "mississippi"
# Obter caracteres únicos
unique_chars = {char for char in text}
print(unique_chars) # Output: {'m', 'i', 's', 'p'}34.4.3) Transformando e Filtrando com Set Comprehensions
Como outras comprehensions, set comprehensions podem incluir transformações e condições:
# Nomes dos alunos
names = ["Alice", "bob", "CHARLIE", "david", "EVE"]
# Obter primeiras letras únicas em maiúsculas
first_letters = {name[0].upper() for name in names}
print(first_letters) # Output: {'A', 'B', 'C', 'D', 'E'}Filtrando com condições:
# Números com duplicatas
numbers = [1, -2, 3, -4, 5, -2, 3, 6, -4]
# Obter números positivos únicos
positive_numbers = {n for n in numbers if n > 0}
print(positive_numbers) # Output: {1, 3, 5, 6}34.4.4) Quando Set Comprehensions São Mais Úteis
Set comprehensions são particularmente valiosas quando:
- Você precisa de valores únicos: Remove duplicatas automaticamente
- A ordem não importa: Conjuntos não têm ordem, então use quando a sequência não é importante
- Você vai realizar operações de conjunto: O resultado pode ser usado com união, interseção etc. (como aprendemos no Capítulo 17)
# Matrículas de alunos em dois cursos
course_a = ["Alice", "Bob", "Charlie", "David"]
course_b = ["Charlie", "David", "Eve", "Frank"]
# Obter alunos únicos em ambos os cursos usando set comprehension
all_students = {student for course in [course_a, course_b] for student in course}
print(all_students) # Output: {'Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank'}34.5) Escolhendo Entre Comprehensions vs Loops
34.5.1) Quando Comprehensions São Melhores
Comprehensions geralmente são preferidas quando você está criando uma nova coleção ao transformar ou filtrar uma existente. Elas são mais concisas, muitas vezes mais legíveis e normalmente mais rápidas do que loops equivalentes.
Comprehensions se destacam quando:
- Criar uma nova coleção a partir de uma existente:
# Bom uso de comprehension
prices = [10.99, 25.50, 8.75, 15.00]
discounted = [price * 0.9 for price in prices]- A transformação é direta:
# Claro e conciso
names = ["alice", "bob", "charlie"]
uppercase_names = [name.upper() for name in names]- Filtrar com base em condições simples:
# Fácil de entender
scores = [85, 92, 78, 65, 88, 55, 73, 95]
passing = [score for score in scores if score >= 70]34.5.2) Quando Loops Tradicionais São Melhores
No entanto, há situações em que loops tradicionais são mais apropriados e legíveis:
Use loops quando:
- A lógica é complexa ou envolve várias etapas:
# Complexo demais para uma comprehension
results = []
for score in scores:
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 70:
grade = "C"
else:
grade = "F"
results.append({"score": score, "grade": grade})Embora você pudesse escrever isso como uma comprehension, seria muito mais difícil de ler.
- Você precisa executar ações além de criar uma coleção:
# O loop é mais claro ao fazer I/O ou efeitos colaterais
for filename in files:
with open(filename) as f:
content = f.read()
print(f"Processing {filename}")
# ... more processing- Você precisa modificar uma coleção existente diretamente (in place):
# Modificar uma lista diretamente (in place) - não dá para usar comprehension
numbers = [1, 2, 3, 4, 5]
for i in range(len(numbers)):
numbers[i] *= 2
print(numbers) # Output: [2, 4, 6, 8, 10]- Você precisa usar break ou continue com lógica complexa:
# Encontrar a primeira ocorrência com processamento adicional
found = None
for item in items:
if item.startswith("target"):
found = item
print(f"Found: {found}")
break34.5.3) Considerações de Legibilidade
O fator mais importante é a legibilidade. Se uma comprehension ficar longa demais ou complexa, quebre em um loop tradicional:
# Difícil de ler - coisa demais acontecendo em uma linha
result = [item.upper().strip() for item in items if len(item) > 5 and item.startswith('a')]
# Melhor - use um loop quando a lógica for complexa
result = []
for item in items:
if len(item) > 5 and item.startswith('a'):
cleaned = item.strip().upper()
result.append(cleaned)Uma boa regra geral: se sua comprehension não cabe confortavelmente em uma linha (ou no máximo duas linhas com formatação clara), considere usar um loop.
34.5.4) Considerações de Desempenho
Comprehensions geralmente são mais rápidas do que loops equivalentes porque são otimizadas no nível do interpretador. No entanto, essa diferença de performance normalmente é insignificante para coleções pequenas a médias.
# Ambas produzem o mesmo resultado
# A comprehension é um pouco mais rápida
squares_comp = [n ** 2 for n in range(1000)]
# O loop é um pouco mais lento, mas mais flexível
squares_loop = []
for n in range(1000):
squares_loop.append(n ** 2)Para a maioria dos propósitos práticos, escolha com base na legibilidade em vez de desempenho. Só otimize por velocidade se o profiling mostrar que uma operação específica é um gargalo.
34.5.5) Combinando Abordagens
Às vezes a melhor solução combina as duas abordagens:
# Usar comprehension para uma transformação simples
student_data = [
{"name": "Alice", "score": 85},
{"name": "Bob", "score": 92},
{"name": "Charlie", "score": 78}
]
# Extrair notas com comprehension
scores = [student["score"] for student in student_data]
# Usar loop para processamento complexo
for student in student_data:
score = student["score"]
if score >= 90:
print(f"{student['name']}: Excellent!")
elif score >= 80:
print(f"{student['name']}: Good job!")
else:
print(f"{student['name']}: Keep working!")34.6) Loops Aninhados e Múltiplas Cláusulas for
34.6.1) Entendendo Múltiplas Cláusulas for
Comprehensions podem incluir múltiplas cláusulas for, o que é equivalente a loops aninhados. A sintaxe é:
[expression for item1 in iterable1 for item2 in iterable2]Isso é equivalente a:
result = []
for item1 in iterable1:
for item2 in iterable2:
result.append(expression)O ponto-chave é que as cláusulas for são lidas da esquerda para a direita, assim como loops aninhados são escritos de cima para baixo.
Vamos começar com um exemplo simples que cria todas as combinações de duas listas:
# Duas listas de valores
colors = ["red", "blue"]
sizes = ["S", "M", "L"]
# Criar todas as combinações
combinations = [(color, size) for color in colors for size in sizes]
print(combinations)
# Output: [('red', 'S'), ('red', 'M'), ('red', 'L'), ('blue', 'S'), ('blue', 'M'), ('blue', 'L')]Isso cria todo pareamento possível de uma cor com um tamanho.
34.6.2) Criando Pares de Coordenadas
Um caso de uso comum é gerar pares de coordenadas:
# Criar uma grade 3x3 de coordenadas
coordinates = [(x, y) for x in range(3) for y in range(3)]
print(coordinates)
# Output: [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]Criando uma tabuada de multiplicação:
# Gerar pares de multiplicação
products = [(x, y, x * y) for x in range(1, 4) for y in range(1, 4)]
for x, y, product in products:
print(f"{x} × {y} = {product}")
# Output:
# 1 × 1 = 1
# 1 × 2 = 2
# 1 × 3 = 3
# 2 × 1 = 2
# 2 × 2 = 4
# 2 × 3 = 6
# 3 × 1 = 3
# 3 × 2 = 6
# 3 × 3 = 934.6.3) Achatando Listas Aninhadas
Múltiplas cláusulas for são úteis para achatar estruturas aninhadas:
# Lista aninhada de números
nested_numbers = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
# Achatar em uma única lista
flat = [num for sublist in nested_numbers for num in sublist]
print(flat) # Output: [1, 2, 3, 4, 5, 6, 7, 8, 9]Isso é equivalente a:
flat = []
for sublist in nested_numbers:
for num in sublist:
flat.append(num)Achatando uma lista de palavras em caracteres:
# Lista de palavras
words = ["cat", "dog", "bird"]
# Obter todos os caracteres de todas as palavras
all_chars = [char for word in words for char in word]
print(all_chars) # Output: ['c', 'a', 't', 'd', 'o', 'g', 'b', 'i', 'r', 'd']34.6.4) Adicionando Condições a Comprehensions Aninhadas
Você pode adicionar condições para filtrar os resultados:
# Criar pares em que a soma é par
pairs = [(x, y) for x in range(5) for y in range(5) if (x + y) % 2 == 0]
print(pairs)
# Output: [(0, 0), (0, 2), (0, 4), (1, 1), (1, 3), (2, 0), (2, 2), (2, 4), (3, 1), (3, 3), (4, 0), (4, 2), (4, 4)]Encontrando elementos comuns entre listas:
# Duas listas de números
list1 = [1, 2, 3, 4, 5]
list2 = [4, 5, 6, 7, 8]
# Encontrar pares em que valores são iguais (elementos comuns)
common = [x for x in list1 for y in list2 if x == y]
print(common) # Output: [4, 5]Nota: Para encontrar elementos comuns, usar interseção de conjuntos é mais eficiente: set(list1) & set(list2), que aprendemos no Capítulo 17.
34.6.5) Dictionary Comprehensions Aninhadas
Você também pode usar múltiplas cláusulas for em dictionary comprehensions:
# Criar um dicionário de somas de coordenadas
coord_sums = {(x, y): x + y for x in range(3) for y in range(3)}
print(coord_sums)
# Output: {(0, 0): 0, (0, 1): 1, (0, 2): 2, (1, 0): 1, (1, 1): 2, (1, 2): 3, (2, 0): 2, (2, 1): 3, (2, 2): 4}34.6.6) Quando Evitar Comprehensions Aninhadas
Embora comprehensions aninhadas sejam poderosas, elas podem rapidamente ficar difíceis de ler. Considere estas diretrizes:
Aceitável - relativamente simples:
# Dois níveis de aninhamento, expressão simples
matrix = [[i * j for j in range(3)] for i in range(3)]
print(matrix) # Output: [[0, 0, 0], [0, 1, 2], [0, 2, 4]]Ficando complexo - considere um loop:
# Três níveis de aninhamento - difícil de ler
result = [[[i + j + k for k in range(2)] for j in range(2)] for i in range(2)]
# Melhor como loops aninhados para clarezaRegra geral: se você tiver mais de duas cláusulas for, ou se a expressão for complexa, use loops aninhados tradicionais:
# Mais claro com loops explícitos
result = []
for i in range(2):
middle = []
for j in range(2):
inner = []
for k in range(2):
inner.append(i + j + k)
middle.append(inner)
result.append(middle)Comprehensions com múltiplas cláusulas for são ferramentas poderosas, mas lembre-se: clareza é mais importante do que brevidade. Se uma comprehension aninhada ficar difícil de entender, é melhor usar loops explícitos.