Pular para o conteúdo
Editor

List comprehension em Python: dict, set e expressões geradoras

Intermediário30 min8 exercícios115 XP

Este tutorial foi traduzido do original em inglês.Read in EnglishLeer en españolЧитать на русскомอ่านภาษาไทยAvisar sobre um erro de tradução

0/8 exercícios

Imagine que você tem uma lista de 100 números e quer uma nova lista só com os pares, cada um multiplicado por 2. Com um laço comum, isso leva quatro linhas. Com uma comprehension (compreensão) do Python, leva uma.

As compreensões são um dos recursos mais queridos do Python. Elas permitem criar novas listas, dicionários e conjuntos descrevendo o que você quer, em vez de escrever instruções passo a passo de como construir isso.

Neste tutorial, você vai aprender os quatro tipos de compreensão (de lista, de dicionário, de conjunto e as expressões geradoras), além de filtros, condicionais e a pergunta importante: quando NÃO usá-las.

List comprehension: o padrão mais comum

Uma list comprehension (compreensão de lista) cria uma nova lista aplicando uma expressão a cada item de uma sequência existente. A sintaxe é: [expression for item in iterable].

Pense nela como um laço for compacto que monta uma lista. Em vez de criar uma lista vazia e ir adicionando itens dentro de um laço, você descreve o resultado em uma única linha.

Laço comum (4 linhas)
numbers = [1, 2, 3, 4, 5]
squares = []
for n in numbers:
    squares.append(n ** 2)
print(squares)  # [1, 4, 9, 16, 25]
List comprehension (1 linha)
numbers = [1, 2, 3, 4, 5]
squares = [n ** 2 for n in numbers]
print(squares)  # [1, 4, 9, 16, 25]
List comprehensions básicas
# Square each number
numbers = [1, 2, 3, 4, 5]
squares = [n ** 2 for n in numbers]
print(squares)
# Convert names to uppercase
names = ['alice', 'bob', 'charlie']
upper_names = [name.upper() for name in names]
print(upper_names)
# Get the length of each word
words = ['hello', 'world', 'python', 'is', 'fun']
lengths = [len(w) for w in words]
print(lengths)
Saída
[1, 4, 9, 16, 25]
['ALICE', 'BOB', 'CHARLIE']
[5, 5, 6, 2, 3]

Adicionando condições às compreensões

Você pode adicionar uma cláusula if para filtrar itens. Só os itens que passam na condição entram na nova lista. A sintaxe é: [expression for item in iterable if condition].

Filtrando com if
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Keep only even numbers
evens = [n for n in numbers if n % 2 == 0]
print(evens) # [2, 4, 6, 8, 10]
# Keep only words longer than 3 characters
words = ['hi', 'hello', 'hey', 'world', 'ok', 'python']
long_words = [w for w in words if len(w) > 3]
print(long_words) # ['hello', 'world', 'python']
Saída
[2, 4, 6, 8, 10]
['hello', 'world', 'python']

Você também pode usar uma expressão if-else para transformar os itens de formas diferentes, de acordo com uma condição. Mas repare na mudança de sintaxe: o if-else vem antes do for, e não depois.

Usando if-else nas compreensões
numbers = [1, 2, 3, 4, 5, 6]
# Label each number as even or odd
labels = ['even' if n % 2 == 0 else 'odd' for n in numbers]
print(labels) # ['odd', 'even', 'odd', 'even', 'odd', 'even']
# Cap scores at 100
raw_scores = [85, 110, 92, 105, 78]
capped = [min(s, 100) for s in raw_scores]
print(capped) # [85, 100, 92, 100, 78]
Saída
['odd', 'even', 'odd', 'even', 'odd', 'even']
[85, 100, 92, 100, 78]

Compreensões de dicionário (dict comprehensions)

As compreensões de dicionário funcionam como as list comprehensions, mas criam dicionários. Use chaves e uma expressão key: value. A sintaxe é: {key: value for item in iterable}.

Compreensões de dicionário básicas
# Create a dict of numbers and their squares
squares = {n: n ** 2 for n in range(1, 6)}
print(squares) # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# Create a dict from two lists using zip()
names = ['Alice', 'Bob', 'Charlie']
scores = [95, 87, 72]
grade_book = {name: score for name, score in zip(names, scores)}
print(grade_book) # {'Alice': 95, 'Bob': 87, 'Charlie': 72}
Saída
{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
{'Alice': 95, 'Bob': 87, 'Charlie': 72}

Você também pode filtrar com if, do mesmo jeito que nas list comprehensions. Isso é ótimo para criar um subconjunto de um dicionário.

Compreensões de dicionário com filtro e transformação
prices = {'apple': 1.50, 'banana': 0.75, 'cherry': 3.00, 'date': 5.00}
# Keep only items under $2
affordable = {fruit: price for fruit, price in prices.items() if price < 2}
print(affordable) # {'apple': 1.5, 'banana': 0.75}
# Swap keys and values
flipped = {price: fruit for fruit, price in prices.items()}
print(flipped) # {1.5: 'apple', 0.75: 'banana', 3.0: 'cherry', 5.0: 'date'}
Saída
{'apple': 1.5, 'banana': 0.75}
{1.5: 'apple', 0.75: 'banana', 3.0: 'cherry', 5.0: 'date'}

Compreensões de conjunto (set comprehensions)

As compreensões de conjunto criam conjuntos (sets), coleções sem duplicatas. Elas usam chaves, como as compreensões de dicionário, mas sem os dois-pontos. A sintaxe é: {expression for item in iterable}.

Compreensões de conjunto
# Get unique first letters from a list of names
names = ['Alice', 'Anna', 'Bob', 'Charlie', 'Chloe']
first_letters = {name[0] for name in names}
print(first_letters) # {'A', 'B', 'C'}
# Get unique word lengths
sentence = 'the quick brown fox jumps over the lazy dog'
lengths = {len(word) for word in sentence.split()}
print(sorted(lengths)) # [3, 4, 5]
Saída
{'B', 'C', 'A'}
[3, 4, 5]

A principal diferença em relação às list comprehensions é que os conjuntos removem duplicatas automaticamente. Embora "Alice" e "Anna" comecem com "A", o conjunto tem um único "A".

Expressões geradoras: compreensões que economizam memória

Uma expressão geradora (generator expression) parece uma list comprehension, mas usa parênteses em vez de colchetes. A grande diferença: ela não cria todos os itens de uma vez. Ela os gera um por vez, sob demanda.

Isso importa quando você trabalha com volumes muito grandes de dados. Uma list comprehension com um milhão de itens cria uma lista de um milhão de itens na memória. Uma expressão geradora quase não usa memória: ela calcula cada item só quando você pede.

List comprehension vs. expressão geradora
# List comprehension - builds the entire list in memory
squares_list = [n ** 2 for n in range(5)]
print(squares_list) # [0, 1, 4, 9, 16]
print(type(squares_list)) # <class 'list'>
# Generator expression - generates items on demand
squares_gen = (n ** 2 for n in range(5))
print(squares_gen) # <generator object ...>
print(type(squares_gen)) # <class 'generator'>
# You can loop through a generator
for sq in squares_gen:
print(sq, end=' ')
print()
Saída
[0, 1, 4, 9, 16]
<class 'list'>
<generator object <genexpr> at 0x4fc5898>
<class 'generator'>
0 1 4 9 16

Expressões geradoras são muito usadas dentro de funções como sum(), max() e min(). Você pode omitir os parênteses extras quando o gerador é o único argumento.

Expressões geradoras dentro de funções
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Sum of squares using a generator (no extra parentheses needed)
total = sum(n ** 2 for n in numbers)
print(f'Sum of squares: {total}')
# Check if any number is negative
has_negative = any(n < 0 for n in numbers)
print(f'Has negative: {has_negative}')
# Check if all numbers are positive
all_positive = all(n > 0 for n in numbers)
print(f'All positive: {all_positive}')
Saída
Sum of squares: 385
Has negative: False
All positive: True

Compreensões aninhadas

Você pode colocar uma cláusula for dentro de outra para lidar com laços aninhados. O laço externo vem primeiro, depois o interno. Isso é útil para achatar listas ou criar grades.

Achatando uma lista aninhada
# Flatten a list of lists
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [num for row in matrix for num in row]
print(flat) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
# This is equivalent to:
flat2 = []
for row in matrix:
for num in row:
flat2.append(num)
print(flat2) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
Saída
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Criando pares de coordenadas
# Create coordinate pairs
coords = [(x, y) for x in range(3) for y in range(3)]
print(coords)
# [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
Saída
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]

Quando NÃO usar compreensões

As compreensões são poderosas, mas nem sempre são a escolha certa. Se uma compreensão é difícil de ler, um laço comum é melhor. Clareza no código sempre vence a esperteza.

Evite compreensões quando: a lógica é complexa, com várias condições; você precisa de efeitos colaterais, como exibir algo dentro do laço; ou a compreensão passa de uns 80 caracteres de largura.

Complexa demais: difícil de ler
result = [x * 2 if x > 0 else -x for x in data
         if x != 0 and x % 3 == 0]
Laço claro: bem mais legível
result = []
for x in data:
    if x != 0 and x % 3 == 0:
        if x > 0:
            result.append(x * 2)
        else:
            result.append(-x)

Além disso, nunca use uma compreensão só pelos efeitos colaterais. Se você está chamando print() ou modificando uma variável externa, use um laço comum. Uma compreensão deve sempre servir para construir uma nova coleção.


Exercícios práticos

Hora de praticar! Estes exercícios cobrem os quatro tipos de compreensão, dos padrões básicos aos mais desafiadores.

Exercício 1: dobre cada número
Escreva o código

Use uma list comprehension para criar uma lista chamada doubled que contenha cada número da lista dada, multiplicado por 2.

Saída esperada:

[2, 4, 6, 8, 10]
numbers = [1, 2, 3, 4, 5]
# Create doubled using a list comprehension
print(doubled)
Exercício 2: filtre os números pares
Escreva o código

Use uma list comprehension com uma cláusula if para criar uma lista chamada evens que contenha apenas os números pares da lista dada.

Saída esperada:

[4, 12, 8, 20, 6]
numbers = [3, 4, 7, 12, 8, 15, 20, 6, 9]
# Create evens using a list comprehension with filtering
print(evens)
Exercício 3: preveja a saída (if ou if-else)
Preveja a saída

Leia este código com atenção e preveja o que ele vai exibir. Repare na posição do if-else.

Digite a saída exata.

nums = [1, 2, 3, 4, 5]
result = ['even' if n % 2 == 0 else 'odd' for n in nums]
print(result)
Exercício 4: crie uma compreensão de dicionário
Escreva o código

Use uma compreensão de dicionário para criar um dicionário chamado name_lengths que associe cada nome ao seu número de letras.

Saída esperada:

{'Alice': 5, 'Bob': 3, 'Charlie': 7}
names = ['Alice', 'Bob', 'Charlie']
# Create name_lengths using a dict comprehension
print(name_lengths)
Exercício 5: vogais distintas com uma compreensão de conjunto
Escreva o código

Use uma compreensão de conjunto para encontrar todas as vogais distintas da palavra dada. Guarde o resultado em uma variável chamada vowels_found e depois exiba-o ordenado, como uma lista.

Saída esperada:

['a', 'e', 'i', 'o']
word = 'conversation'
# Find unique vowels using a set comprehension
# Print them sorted
Exercício 6: corrija a sintaxe da compreensão
Corrija o erro

Este código tenta criar uma lista em que os números maiores que 5 recebem o rótulo 'high' (alto) e os demais, 'low' (baixo). Mas a sintaxe está errada e o programa dá erro. Corrija-o.

Saída esperada:

['low', 'high', 'low', 'high', 'low', 'high']
nums = [3, 8, 2, 9, 1, 7]
result = ['high' for n in nums if n > 5 else 'low']
print(result)
Exercício 7: transforme um laço em uma compreensão
Melhore o código

Reescreva o laço abaixo como uma única list comprehension. A saída deve continuar exatamente a mesma.

Saída esperada:

[1, 9, 25, 49, 81]
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
result = []
for n in numbers:
if n % 2 != 0:
result.append(n ** 2)
print(result)
Exercício 8: achate uma matriz
Escreva o código

Use uma list comprehension com duas cláusulas for para achatar a matriz dada (uma lista de listas) em uma única lista simples. Depois, exiba a soma de todos os itens usando uma expressão geradora dentro de sum().

Saída esperada:

[1, 2, 3, 4, 5, 6, 7, 8, 9]
45
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
# Flatten using a list comprehension with nested for clauses
# Print the flat list
# Print the sum using a generator expression

Resumo: o que você aprendeu sobre compreensões em Python

Uma recapitulação de tudo o que você já sabe:

TipoSintaxeCria
List comprehension[expr for x in items]Uma lista
Lista filtrada[expr for x in items if cond]Uma lista filtrada
Lista transformada[a if cond else b for x in items]Uma lista mapeada
Compreensão de dicionário{k: v for x in items}Um dicionário
Compreensão de conjunto{expr for x in items}Um conjunto (sem duplicatas)
Expressão geradora(expr for x in items)Um gerador (calcula sob demanda)
Compreensão aninhada[expr for a in X for b in a]Uma lista achatada

As compreensões são um dos recursos mais característicos do Python. Elas deixam o código mais curto, mais legível (quando bem usadas) e, muitas vezes, mais rápido do que os laços equivalentes.

O que vem a seguir?

Agora que você sabe criar e transformar coleções com facilidade, está pronto para conhecer as tuplas em Python: sequências imutáveis, perfeitas para dados fixos como coordenadas, registros e valores retornados por funções.

Você vai aprender por que a imutabilidade é útil, como funcionam o empacotamento e o desempacotamento de tuplas e quando escolher uma tupla em vez de uma lista.

Tutoriais relacionados

Este tutorial foi útil?