Curso de Python / Compreensões de lista, dicionário e conjunto

Uma compreensão cria uma coleção ao transformar elementos ou selecionar os que satisfazem uma condição. Use essa sintaxe para uma transformação curta e legível; quando forem necessárias várias etapas, tratamento de exceções ou efeitos como gravar arquivos, prefira um laço comum.

Separe a expressão de transformação do filtro

A forma de lista é [expressao for item in origem if condicao]. O if depois do for decide se o item participa do resultado. Uma expressão como a if condicao else b, colocada antes do for, escolhe qual valor será produzido para cada item incluído.

Por exemplo, [x * 2 for x in range(4) if x % 2 == 0] escolhe os valores 0 e 2, depois os multiplica por dois, produzindo [0, 4]. O filtro é aplicado antes da expressão de resultado para cada item. O tutorial oficial de compreensões compara a sintaxe com um laço de construção de lista.

Criar uma nova lista não modifica, por si só, a coleção externa de origem nem faz uma cópia profunda dos objetos internos. As expressões usadas determinam quais objetos serão compartilhados e podem ter seus próprios efeitos. Não suponha que uma compreensão torne uma transformação independente ou livre de alterações só porque usa uma sintaxe curta.

Crie listas, dicionários e conjuntos em um programa

Salve o código completo em UTF-8 como comprehensions.py, na pasta do projeto. Execute python comprehensions.py com o ambiente selecionado. No macOS ou Ubuntu, fora de um ambiente virtual, use python3 se esse for o comando da instalação. Nenhum pacote ou arquivo externo é necessário.

amounts = [3500, -1, 8000, 0]
valid = [x for x in amounts if x >= 0]
labels = ["paid" if x > 0 else "free" for x in valid]
records = [("food", 3500), ("bus", 2500)]
by_name = {name: amount for name, amount in records}
remainders = {x % 3 for x in valid}
print(valid)
print(labels)
print(by_name)
print(sorted(remainders))

A saída esperada é:

[3500, 8000, 0]
['paid', 'paid', 'free']
{'food': 3500, 'bus': 2500}
[0, 2]

valid mantém os valores maiores ou iguais a zero. O nome significa, neste exercício, apenas que esse filtro foi satisfeito; ele não representa uma validação completa de dados externos. Em labels, a expressão condicional transforma os valores positivos em paid, pago, e zero em free, gratuito. O número de rótulos corresponde ao número de itens de valid.

A compreensão de dicionário associa os nomes dos registros aos valores. A compreensão de conjunto guarda os restos das divisões por três. Como 3500 e 8000 deixam o mesmo resto 2, o conjunto tem apenas 0 e 2. sorted() produz uma lista ordenada para exibir esse conjunto.

Considere as regras de repetição de chaves e valores

Em uma compreensão de dicionário, uma chave repetida recebe o último valor encontrado. Portanto, {name: amount for name, amount in records} não calcula a soma das ocorrências de cada nome. Se houver dois registros de food, um valor substitui o outro. A referência de construção de coleções descreve a avaliação das compreensões e dos dicionários.

Para acumular valores repetidos, use uma regra de soma explícita, como no programa de totais por categoria com dicionários. A forma das chaves e a operação feita com os valores são decisões diferentes.

Uma compreensão de conjunto elimina elementos repetidos; ela não mantém a quantidade nem a ordem das ocorrências. Uma compreensão de lista mantém cada resultado incluído, mesmo que os valores sejam iguais. Escolha a estrutura de acordo com o que precisa preservar.

Antes de abreviar um processamento, escreva-o como um laço claro. Para o exemplo de números pares, crie uma lista vazia, percorra range(4), teste a condição e use append(x * 2) apenas nos itens aceitos. A sequência de passos deve continuar reconhecível na compreensão. Se houver muitos testes ou efeitos, manter o laço pode comunicar melhor a regra.

Confira resultados vazios, compartilhamento e efeitos

Se nenhum item passar pelo filtro, o resultado será uma coleção vazia. Defina o que isso significa antes de acessar o primeiro elemento ou calcular uma média dividindo pela quantidade de itens. Um filtro não garante que sempre haverá algum resultado.

Se a expressão retornar o próprio dicionário ou lista de origem, o novo contêiner continuará apontando para esse objeto. Uma alteração posterior no conteúdo interno pode aparecer nas duas coleções. A aula sobre alterações e cópias de listas ajuda a reconhecer esse compartilhamento.

  1. No programa completo, altere apenas o filtro de x >= 0 para x > 0. Confira [3500, 8000], dois rótulos paid e o resultado de restos [2]. O dicionário de nomes não muda.
  2. Restaure o filtro. Acrescente ("food", 4500) ao final de records. O campo food passa a valer 4500, e não a soma 8000. Os resultados calculados a partir de amounts não mudam.
  3. Remova o registro acrescentado e confirme as quatro linhas originais.

Não use uma compreensão de lista somente para executar print() ou gravar arquivos: isso cria uma lista de retornos sem utilidade para a tarefa. Um for comum deixa esses efeitos explícitos e evita confundir um processamento com a construção de uma nova coleção.