Comprensión de la lista de una línea: variantes if-else

178

Se trata más de la sintaxis de comprensión de la lista de Python. Tengo una lista de comprensión que produce una lista de números impares de un rango dado:

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

Esto hace un filtro: tengo una lista de origen, donde elimino los números pares ( if x % 2). Me gustaría usar algo como si, entonces, más aquí. El siguiente código falla:

>>> [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

Hay una expresión de python como if-else:

1 if 0 is 0 else 3

¿Cómo usarlo dentro de una lista de comprensión?

ducin
fuente
1
Fow lo que vale, tienes una "comprensión de la lista", no un generador. La sintaxis final es la misma, excepto que los generadores usan en ()lugar de [].
mgilson
2
Me tomó un tiempo entender por qué if x % 2 elimina los números pares (en lugar de mantenerlos), es porque cuando xaparece la x % 2expresión 0, lo que, a su vez, se evalúa False, mientras que cualquiera intexcepto se 0evalúa True.

Respuestas:

328

x if y else zes la sintaxis de la expresión que está devolviendo para cada elemento. Por lo tanto necesitas:

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

La confusión surge del hecho de que está utilizando un filtro en el primer ejemplo, pero no en el segundo. En el segundo ejemplo, solo está asignando cada valor a otro, utilizando una expresión de operador ternario.

Con un filtro, necesitas:

[ EXP for x in seq if COND ]

Sin filtro necesitas:

[ EXP for x in seq ]

y en su segundo ejemplo, la expresión es "compleja", que implica una if-else.

shx2
fuente
2
Tengo una pregunta ... [x for x in range(1, 10) if x % 2]es la sintaxis correcta. [x if x % 2 for x in range(1, 10)]- esto no es, pero [x if x%2 else x*100 for x in range(1, 10)]es de nuevo, la sintaxis correcta. ¿Cómo?
ducin
@tkoomzaaskz en su segundo ejemplo, este no es un operador ternario si no existe (falta el else), ni un filtro (ya que es EXPparte de la comprensión de la lista)
shx2
3
@tkoomzaaskz Para aclarar más, tenga en cuenta que puede agregar un segundo ifal final: [x if x%2 else x*100 for x in range(1, 10) if not x%3]el primero ifes parte del operador ternario, el segundo ifes parte de la sintaxis de comprensión de la lista. El todo x if x%2 else x*100está "en el mismo nivel" que un simple 2*x, es la expresión para evaluar en el lado izquierdo de la for, cuando el filtrado de if not x%3ya ha tenido lugar.
zx81 01 de
Hola, ¿una declaración de una línea sería más eficaz que hacerla en dos líneas como for i in x:y luego en el bucle for if i == y:?
Alexis.Rolland
23
[x if x % 2 else x * 100 for x in range(1, 10) ]
lucasg
fuente
12

También puede hacerlo con la comprensión de la lista:

A=[[x*100, x][x % 2 != 0] for x in range(1,11)]
print A
Stefan Gruenwald
fuente
1
Muy agradable. Una rebanada booleana. Gracias, me diste una solución más fácil de leer.
También puede asignar dos veces así: A, B = [10,11] [a == 19], [1,14] [a == 20]
Stefan Gruenwald
10

Solo otra solución, espero que a alguien le guste:

Usando: [Falso, Verdadero] [Expresión]

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

Pude hacer esto

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