2.30. Compreensões¶
Uma compreensão constrói uma nova lista, conjunto, dicionário ou gerador a partir de um iterável existente, em uma única expressão. É uma substituição para o padrão comum de começar com um contêiner vazio e ir adicionando em um laço.
2.30.1. Compreensões de lista¶
squares = [x * x for x in range(5)]
print(squares)
Saída:
[0, 1, 4, 9, 16]
O mesmo laço escrito por extenso:
squares = []
for x in range(5):
squares.append(x * x)
A forma de compreensão é uma única expressão que constrói a lista no local. Não há squares = [] nem .append – o resultado é o valor da compreensão.
A expressão inicial produz cada item; a cláusula for nomeia a variável do laço; um if opcional filtra os itens.¶
2.30.2. Filtrando com if¶
Uma cláusula if opcional mantém apenas os itens que correspondem:
evens = [x for x in range(10) if x % 2 == 0]
print(evens)
Saída:
[0, 2, 4, 6, 8]
O filtro é executado antes da expressão inicial – x % 2 == 0 é verificado primeiro; apenas os valores correspondentes chegam a x para a saída.
2.30.3. Compreensões de dicionário e de conjunto¶
A mesma forma funciona com literais de dicionário e de conjunto.
Uma compreensão de dicionário tem um par key: value antes do for:
squares = {x: x * x for x in range(5)}
print(squares)
Saída:
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
Uma compreensão de conjunto usa chaves e uma única expressão:
unique_lengths = {len(w) for w in ["a", "bb", "c", "bb"]}
print(unique_lengths)
Saída:
{1, 2}
2.30.4. Expressões geradoras¶
Parênteses produzem uma expressão geradora em vez de uma lista. Os valores são calculados um de cada vez, sob demanda:
total = sum(x * x for x in range(1000))
Nenhuma lista de um milhão de itens é construída. Os valores fluem um a um para sum(), que os soma e descarta cada um conforme avança.
Expressões geradoras são a escolha certa ao alimentar valores em uma função de redução (sum(), max(), any(), all()) ou em qualquer outro código que consome iteradores – elas economizam a memória que a lista equivalente teria usado.
2.30.5. Quando não usar uma compreensão¶
Compreensões são concisas, mas nem sempre mais claras. Recorra a um laço for comum quando:
O corpo precisa de mais de uma instrução (uma compreensão comporta exatamente uma expressão).
O corpo tem efeitos colaterais (imprimir, escrever em um arquivo) – compreensões servem para construir uma coleção, não para executar ações.
O filtro ou a transformação tem tantas partes que a compreensão deixa de ser lida da esquerda para a direita.