Compreensão de lista de uma linha: variantes if-else

178

É mais sobre sintaxe de compreensão da lista python. Eu tenho uma compreensão de lista que produz lista de números ímpares de um determinado intervalo:

[x for x in range(1, 10) if x % 2]

Isso cria um filtro - eu tenho uma lista de fontes, onde removo números pares ( if x % 2). Eu gostaria de usar algo como se-então-outro aqui. O código a seguir falha:

>>> [x for x in range(1, 10) if x % 2 else x * 100]
  File "<stdin>", line 1
    [x for x in range(1, 10) if x % 2 else x * 100]
                                         ^
SyntaxError: invalid syntax

Há uma expressão python como if-else:

1 if 0 is 0 else 3

Como usá-lo dentro de uma compreensão de lista?

ducin
fonte
1
Veja o que vale, você tem uma "compreensão da lista", não um gerador. A sintaxe final é a mesma, exceto que os geradores usam em ()vez de [].
mgilson
2
Demorei um pouco para entender por que os números pares foram if x % 2 eliminados (em vez de mantê-los) - é porque quando xé que a x % 2expressão resulta 0, que, por sua vez, avalia como False, enquanto qualquer um intexceto 0avalia True.

Respostas:

328

x if y else zé a sintaxe da expressão que você está retornando para cada elemento. Assim você precisa:

[ x if x%2 else x*100 for x in range(1, 10) ]

A confusão surge do fato de você estar usando um filtro no primeiro exemplo, mas não no segundo. No segundo exemplo, você está mapeando apenas cada valor para outro, usando uma expressão de operador ternário.

Com um filtro, você precisa:

[ EXP for x in seq if COND ]

Sem um filtro, você precisa:

[ EXP for x in seq ]

e no seu segundo exemplo, a expressão é "complexa", que envolve um if-else.

shx2
fonte
2
Eu tenho uma pergunta ... [x for x in range(1, 10) if x % 2]é a sintaxe correta. [x if x % 2 for x in range(1, 10)]- isto não é, mas [x if x%2 else x*100 for x in range(1, 10)]é novamente, sintaxe correta. Por quê?
ducin
@tkoomzaaskz em seu segundo exemplo, este não é um operador ternário se-mais (faltando o else), nem um filtro (uma vez que é na EXPparte da lista de compreensão)
shx2
3
@tkoomzaaskz Para esclarecer, note que você pode adicionar um segundo ifno final: [x if x%2 else x*100 for x in range(1, 10) if not x%3]O primeiro iffaz parte do operador ternário, o segundo iffaz parte da sintaxe de compreensão da lista. O todo x if x%2 else x*100é "no mesmo nível" como um simples 2*x, é a expressão a ser avaliada no lado esquerdo do for, quando a filtragem if not x%3já tiver ocorrido.
Zx81
Olá, uma declaração de uma linha seria mais eficiente do que fazê-la em duas linhas como for i in x:e depois no loop for if i == y:?
Alexis.Rolland
23
[x if x % 2 else x * 100 for x in range(1, 10) ]
lucasg
fonte
12

Você também pode fazer isso com a compreensão da lista:

A=[[x*100, x][x % 2 != 0] for x in range(1,11)]
print A
Stefan Gruenwald
fonte
1
Muito agradável. Uma fatia booleana. Obrigado, você me deu uma solução mais fácil de ler.
Também pode fazer duplo atribuir assim: A, B = [10,11] [a == 19], [1,14] [a == 20]
Stefan Gruenwald
10

Apenas mais uma solução, espero que alguém goste:

Usando: [Falso, Verdadeiro] [Expressão]

>>> map(lambda x: [x*100, x][x % 2 != 0], range(1,10))
[1, 200, 3, 400, 5, 600, 7, 800, 9]
>>>
James Sapam
fonte
3

Eu consegui fazer isso

>>> [x if x % 2 != 0 else x * 100 for x in range(1,10)]
    [1, 200, 3, 400, 5, 600, 7, 800, 9]
>>>
anudeep
fonte