As list comprehensions do python surgem para, além de poupar que escrevamos códigos prolixos e demasiadamente extensos utilizando laços, seu uso também é uma boa alternativa ao uso das funções lambda do python junto com filter, map, reduce, etc. Ou seja, list comprehensions são amplamente utilizadas em todo lugar, mas é normal que pessoas que estão inciando na linguagem não peguem de primeira esse conceito, por se tratar do que chamamos de código pythonico.
Primeiro, devemos nos lembrar que toda list/tuple/dict/set comprehension segue a mesma estrutura de argumentos:
lista_de_retorno = [< valor que vocë quer que seja retornado > for
< iterador > in
< iteravel > if
< condição >]
É bom lembrar que a parte do if pode não existir, só coloquei ele por se encaixar melhor na sua dúvida.
Agora, se analisarmos melhor a list comprehension que você mencionou acima, percebemos que ela é uma simplificação de algo maior:
inteiros = [1,3,4,5,7,8,9]
pares = list()
for x in inteiros:
if x%2 == 0:
pares.append(x)
Acredito que com a versão extendida acima fique mais claro o que estamos fazendo na expressão pares = [x for x in inteiros if x % 2 == 0]
: Para cada valor x
da lista de inteiros
queremos colocar ele na lista pares
caso o resto da divisão por 2 seja igual a 0.
Por último, a lógica por trás da condição if x%2 == 0
na verdade é mais simples do que parece. Se você pegar qualquer número par, ele sempre poderá ser divido por 2, logo, o resto dessa divisão sempre será 0, o que não ocorre com números ímpares (o resto da divisão sempre será 1).
Espero ter ajudado :)