Compreensão de listas (list comprehension)
É muito comum usarmos um laço de repetição para produzir e acumular elementos em uma estrutura de dados, vamos ver um exemplo meio bobinho de um for
que acrescenta itens em uma lista. São pontos com um x
que vai crescendo de 10 em 10 e o y
produzido ‘pseudo-aleatório’, com a função embutidada do Processing, random()
:
pontos = []
for i in range(10):
x = i * 10
y = random(-100, 100)
ponto.append((x, y)) # os parenteses extra criam uma tupla
Existe um maneira alternativa de fazer isso usando a sintaxe chamada compreensão de lista, compare:
pontos = [(i * 10, random(-100, 100)) for i in range(10)]
Veja se você consegue identificar, nos exemplos acima, os elementos do seguinte padrão geral, que usa um laço de repetição para construir a lista:
lista_resultante = []
for «valor» in «iterável»:
lista_resultante.append(«novo_elemento») # o novo elemento é acrescentado
E a forma reescrita:
lista_resultante = [«novo_elemento» for «valor» in «iterável»]
É possível ainda “filtrar”, usar uma condição que permite ou não produzir novos elementos.
lista_resultante = []
for «valor» in «iterável»:
if «condição»: # a condição depende do valor
lista_resultante.append(«novo_elemento») # o novo elemento é acrescentado
Que pode ser reescrito assim:
lista_resultante = [«novo_elemento» for «valor» in «iterável» if «condição»]
Mais exemplos
Sem “filtragem”
dimensoes_retangulos = [(10, 20), (20, 30), (10, 30), (30, 30), (30, 10)]
areas = []
for a, b in dimensoes_retangulos:
areas.append(a * b)
areas = [a * b for a, b in dimensoes_retangulos]
Agora com “filtragem”, ignorando quadrados!
areas = []
for a, b in dimensoes_retangulos:
if a != b: # se `a` diferente de `b`, vai ignorar a == b
areas.append(a * b)
areas = [a * b for a, b in dimensoes_retangulos if a != b]
Expressões geradoras
Se você não precisa dessa coleção de valores mais de uma vez, pode evitar que ela seja guardada na memória, usando expressões geradoras (generator expressions) substituindo os colchetes por parênteses, e até mesmo omitindo os parênteses se a expressão for posta como argumento de uma função:
# soma os quadrados dos números pares entre 0 e 98 (o 100 não está incluso).
soma_quadrados = sum(n * n for n in range(100) if n % 2 == 0) # 161700
Compreensão de conjuntos e dicionários
dimensoes_retangulos = [(10, 20), (20, 30), (10, 30), (30, 30), (30, 10), (5, 40)]
areas_sem_repetir = {a * b for a, b in dimensoes_retangulos}
print(areas_sem_repetir) # set([900, 200, 300, 600])
Um dicionário “pré-calculado” das áreas
areas_dict = {(a, b): a * b for a, b in dimensoes_retangulos}
# {(30, 30): 900, (20, 30): 600, (10, 30): 300,
# (10, 20): 200, (30, 10): 300, (5, 40): 200
# }