2010-11-19 5 views
7

¿se puede escribir esto en una línea sin Comprensión de la lista?for-if without list comprensión en una línea

for x in vec: 
    if x > 3: 
     ... 
     ... 
+10

¿Por qué no?/¿Por qué 1 línea? – kennytm

+0

No estoy muy familiarizado con ellos, pero ¿sería adecuada una declaración 'lambda' aquí? – Blender

+0

@blender: Un 'lambda' solo sería una tontería. Como predicado para 'i-/filter', sí. – delnan

Respuesta

3

No, no se puede. Los Python language reference estados: 'cláusulas' 'suite' declaraciones

compuestos constan de una o más Una cláusula consta de una cabecera y una La cláusula cabeceras de una declaración particular compuesto están todos en el mismo nivel de sangría. Cada encabezado de cláusula comienza con una palabra clave de identificación única y finaliza con dos puntos. Una suite es un grupo de declaraciones controladas por una cláusula. Un conjunto puede ser una o más declaraciones simples separadas por punto y coma en la misma línea que el encabezado, siguiendo los dos puntos del encabezado, o puede ser una o más sentencias indentadas en las líneas subsiguientes. Solo el último forma de conjunto puede contener declaraciones compuestas anidadas; lo siguiente es ilegal, sobre todo porque no sería claro a qué si la cláusula siguiente una cláusula else pertenecería:

if test1: if test2: print x 

De hecho, Python genera un SyntaxError de las FI anidados anteriores. De manera más formal con respecto for, esto es su gramática en Python:

for_stmt ::= "for" target_list "in" expression_list ":" suite 
       ["else" ":" suite] 

suite   ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT 

stmt_list  ::= simple_stmt (";" simple_stmt)* [";"] 

Tenga en cuenta que cuando for va seguida de una declaración sin una muesca, esta indicación debe ser una stmt_list, que sólo permite simple_stmt casos. simple_stmt es la siguiente:

simple_stmt ::= expression_stmt 
       | assert_stmt 
       | assignment_stmt 
       | augmented_assignment_stmt 
       | pass_stmt 
       | del_stmt 
       | print_stmt 
       | return_stmt 
       | yield_stmt 
       | raise_stmt 
       | break_stmt 
       | continue_stmt 
       | import_stmt 
       | global_stmt 
       | exec_stmt 

que no incluye instrucciones compuestas como if y for.


Dicho esto, tenga en cuenta que la sintaxis de Python apunta a la claridad. Por lo tanto, es mejor no anidar tales declaraciones, esto es para lo que se hicieron los generadores/listas de comprensión. Si considera que su cálculo es lo suficientemente simple para una sola línea, entonces las comprensiones son para usted. De lo contrario, realmente no desea saturar el código al tener todo en una sola línea, divídalo bien con sangría. Algunas líneas adicionales no cuestan mucho estos días.

+1

No creo que él estuviera preguntando si podía poner esas 2 declaraciones en una línea. Creo que solo quiere que el efecto general de esas dos declaraciones ocurra en una línea. – Gerrat

+0

@Eli: Dado que puso dos líneas de puntos suspensivos en el ejemplo, está haciendo algo procesal con 'x', haciendo que la lista de comprensiones sea una solución inaceptable. ** Las listas de comprensión no son una forma de convertir ningún bucle en un solo delineador **. – delnan

+0

@delnan: podrías tener razón, realmente no lo sé. ¿No es la intención-intención-interpretación un juego SOO divertido? :-) Animo a Roberto a aclarar lo que realmente quiere –

-1

Se puede imaginar algunas cosas como esta: expresiones

def do_something(value): 
    ... 

def do_otherthing(value): 
    ... 


for x in t: do_something(x) if x>3 else do_otherthing(x) 
+0

eso es exactamente lo que no pidió: "sin Comprensión de listas" –

+1

Lea la pregunta nuevamente. –

+0

La pregunta específicamente no pide esto, de manera propagable porque los '...' son varios enunciados, en cuyo caso una comprensión de lista no sería idiomática. – delnan

0

puede ser, aunque las listas por comprensión/generador son el tipo exacto de lo que se debe utilizar aquí. Dependiendo de lo que quieras hacer en tu bloque if, puedes usar alguna forma de map o reduce, pero la lista de comprensiones y expresiones de generador es probablemente la mejor manera de hacerlo.

+0

Necesito escribir varias líneas después del if, así que eso no va a volar – Roberto

+0

@Roberto así que escriba una función que haga lo que necesita y use eso en la lista de comprensión –

+0

luego remuevo una línea para el for/if cada vez que tengo que hacer algo así, pero agrego una línea para declarar la función :) – Roberto

0

para x en el filtro (lambda i: i> 3, VEC):

+0

Tenga en cuenta que en Python 2, esto creará instantáneamente una nueva lista, en lugar de generar los valores de forma perezosa. – delnan

+0

http://docs.python.org/library/itertools.html#itertools.ifilter –

3

Ver @KennyTM ... ninguna razón para comprimir tanto.

Lo que se dice, for x in (i in vec if i > 3) hace el trabajo, así como itertools.ifilter (o simplemente la orden interna filter en Python 3) con un predicado lambda x: x > 3. También funcionan con todos los iterables y son flojos (por ejemplo, si break durante el bucle, no revisó demasiado un elemento).

+0

El punto completo, como el OP dice en un comentario, es que "si * x * es una palabra grande, tengo que escribirla dos veces "(momento de arrancarse el cabello), entonces probablemente un' filtro' + 'lambda' es la respuesta adecuada para esta ... pregunta. – tzot