List comprehension em Python: dict, set e expressões geradoras
Este tutorial foi traduzido do original em inglês.Read in EnglishLeer en españolЧитать на русскомอ่านภาษาไทยAvisar sobre um erro de tradução
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.
numbers = [1, 2, 3, 4, 5]
squares = []
for n in numbers:
squares.append(n ** 2)
print(squares) # [1, 4, 9, 16, 25]numbers = [1, 2, 3, 4, 5]
squares = [n ** 2 for n in numbers]
print(squares) # [1, 4, 9, 16, 25][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].
[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.
['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}.
{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.
{'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}.
{'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.
[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.
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.
[1, 2, 3, 4, 5, 6, 7, 8, 9] [1, 2, 3, 4, 5, 6, 7, 8, 9]
[(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.
result = [x * 2 if x > 0 else -x for x in data
if x != 0 and x % 3 == 0]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.
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]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]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.
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}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']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']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]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]
45Resumo: o que você aprendeu sobre compreensões em Python
Uma recapitulação de tudo o que você já sabe:
| Tipo | Sintaxe | Cria |
|---|---|---|
| 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.