2009-04-21 15 views
8

¿Es posible tener algo como:¿Declaraciones múltiples en comprennsions de lista en Python?

list1 = ... 

currentValue = 0 
list2 = [currentValue += i, i for i in list1] 

lo he intentado, pero no funcionó? ¿Cuál es la sintaxis correcta para escribir esos?

EDITAR: la declaración de impresión fue un ejemplo. En realidad, estoy incrementando un valor fuera del ciclo.

+0

¿Qué hay de malo en lo común para la declaración? ¿Por qué molestarse con esto cuando tiene una declaración perfectamente buena? ¿Qué estás intentando lograr? –

+1

Nada, solo quiero ver si es posible con comprennsions de listas en Python. –

Respuesta

23

Declaraciones no se puede ir dentro de las expresiones en Python; fue una complicación que fue deliberadamente diseñada fuera del lenguaje. Para este problema, intente utilizar una complicación que hizo para convertirlo en el lenguaje: generadores.Ver:

def total_and_item(sequence): 
    total = 0 
    for i in sequence: 
     total += i 
     yield (total, i) 

list2 = list(total_and_item(list1)) 

El generador de un recuento actualizado de los elementos vistos hasta ahora, y prefijos que a cada elemento, al igual que parece que se trata de hacer ejemplo. Por supuesto, un bucle directo podría ser incluso más simple, que crea una lista vacía en la parte superior y simplemente llama a append() ¡mucho! :-)

+0

+1 por mencionar que las declaraciones están excluidas de las expresiones (y mucho menos _multiple_ statements :-), más la recomendación de enfoques más explícitos. –

0

En primer lugar, es probable que no desee utilizar print. No devuelve nada, por lo tanto, utilice un loop convencional for si solo desea imprimir cosas. Lo que se busca es:

>>> list1 = (1,2,3,4) 
>>> list2 = [(i, i*2) for i in list1] # Notice the braces around both items 
>>> print(list2) 
[(1, 2), (2, 4), (3, 6), (4, 8)] 
2

No estoy muy seguro de lo que estamos tratando de hacer, pero es probable que sea algo así como

list2 = [(i, i*2, i) for i in list1] 
print list2 

La declaración en la lista de la comprensión tiene que ser una sola declaración, pero siempre se podría hacer una llamada de función:

def foo(i): 
    print i 
    print i * 2 
    return i 
list2 = [foo(i) for i in list1] 
2

He aquí un ejemplo de another question:

[i for i,x in enumerate(testlist) if x == 1] 

el generador enumerate devuelve un 2-tuple que va en i, x.

1

Imprimir es algo raro de llamar en una lista de comprensión. Ayudaría si nos mostrara qué salida quiere, no solo el código que no funciona.

Aquí hay dos conjeturas para usted. De cualquier manera, el punto importante es que la declaración de valor en una lista de comprensión debe ser solo valor. No puede insertar varios elementos a la vez. (Si eso es lo que estamos tratando de hacer, pase a la segunda ejemplo.)

list1 = [1, 2, 3] 
list2 = [(i, i*2, i) for i in list1] 
# list2 = [(1, 2, 1), (2, 4, 2), (3, 6, 3)] 

Para obtener una lista plana:

list1 = [1, 2, 3] 
tmp = [(i, i*2) for i in list1] 
list2 = [] 
map(list2.extend, tmp) 
# list2 = [1, 2, 1, 2, 4, 2, 3, 6, 3] 

Editar: incremento de un valor en el medio de la lista la comprensión es aún extraña. Si realmente necesita hacerlo, es mejor que solo escriba un bucle for normal y añada valores a medida que avanza. En Python, esta habilidad casi siempre se tilda de "antiponética". Hazlo si tienes que hacerlo, pero obtendrás un final inigualable en foros como este. ;)

+0

Gracias, básicamente, necesito incrementar un valor fuera de la lista de comprensión. –

+0

¿Puedes escribir lo que estás haciendo como un bucle "for item in list1"? Será más fácil averiguar si es una buena opción para una lista de comprensión de esa manera. – ojrac

0

No puede hacer múltiples instrucciones, pero puede hacer una llamada de función. Para hacer lo que parece querer anterior, se puede hacer:

list1 = ... 
list2 = [ (sum(list1[:i], i) for i in list1 ] 

en general, ya que las listas por comprensión son parte de la parte 'funcional' de pitón, que está restringido a las funciones .... Otras personas han sugerido que podría escribir sus propias funciones si es necesario, y esa también es una sugerencia válida.

+0

¿No generará n listas, donde n es la longitud de la primera lista? El resultado, si la lista fuera miles de elementos, podría tomar demasiado tiempo. –

+0

Claro, pero la eficiencia no era el objetivo: usar una lista de comprensión era. Su solución de generador es obviamente mucho más eficiente. – pjz

1

Para su ejemplo Editado:

currentValue += sum(list1) 

o:

for x in list1: 
    currentValue += x 

Las listas por comprensión son grandes, los amo, pero no hay nada malo con el humilde bucle for y no deberías tenga miedo de usarlo :-)

EDITAR: "¿Y qué pasa si quiero aumentar el valor de los valores recopilados?"

Bueno, ¿qué quieres aumentar? ¡Tienes todo el poder de Python a tu disposición!

Incremento por x-cuadrado?

for x in list1: 
    currentValue += x**2 

¿Incrementar por alguna función de xy su posición en la lista?

for i, x in enumerate(list1): 
    currentValue += i*x 
+0

Pero, ¿qué ocurre si quiero aumentar el valor de los valores recopilados? –

1

¿Por qué crear una lista duplicada? Parece que todo lo que la lista de comprensión haría es solo sumar los contenidos.

¿Por qué no?

list2 = list(list1) #this makes a copy 
currentValue = sum(list2) 
2

Como se ha dicho pjz, puede utilizar las funciones, por lo que aquí se puede utilizar un cierre para realizar un seguimiento del valor del contador:

# defines a closure to enclose the sum variable 
def make_counter(init_value=0): 
    sum = [init_value] 
    def inc(x=0): 
     sum[0] += x 
     return sum[0] 
    return inc 

A continuación, se hace lo que quiere con lista1:

list1 = range(5) # list1 = [0, 1, 2, 3, 4] 

Y ahora con sólo dos líneas, obtenemos: lista2

counter = make_counter(10) # counter with initial value of 10 
list2 = reduce(operator.add, ([counter(x), x] for x in list1)) 

Al final, lista2 contiene:

[10, 0, 11, 1, 13, 2, 16, 3, 20, 4] 

que es lo que quería, y se puede obtener el valor del contador después del bucle con una llamada:

counter() # value is 20 

Por último, se puede reemplazar el cierre por cualquier tipo de operación que desee, aquí tenemos un incremento, pero depende de usted. Nótese también que utilizamos un reducen a aplanar lista2, y este pequeño truco requiere importar operador antes de llamar a la línea con el de reducir:

import operator 
Cuestiones relacionadas