2012-04-24 10 views
27

Quiero usar el operador de asignación en una lista de comprensión. ¿Cómo puedo hacer eso?¿Cómo puedo hacer tareas en una lista de comprensión?

El siguiente código es una sintaxis no válida. Me refiero a establecer lst[0] a una cadena vacía '' si coincide con pattern:

[ lst[0] = '' for pattern in start_pattern if lst[0] == pattern ] 

Gracias!

+3

Creo que tiene esto dentro ... – dawg

+4

Esto no es muy claro. Esa es una señal de advertencia inmediata. –

Respuesta

20

Parece que está confundiendo list comprehension con looping constructs en Python.

¡Una lista de comprensión produce - una lista! No se presta a una sola tarea en una lista existente. (Aunque puede torturar la sintaxis para hacer eso ...)

Si bien no está exactamente claro lo que está tratando de hacer con su código, creo que es más similar al bucle sobre la lista (control de flujo) vs producir una lista (lista por comprensión)

bucle sobre la lista como esta:

for pattern in patterns: 
    if lst[0] == pattern: lst[0]='' 

Esa es una forma razonable de hacer esto, y es lo que haría en C, Pascal, etc, pero se también puede simplemente probar la lista para el único valor y cambiarlo:

if lst[0] in patterns: lst[0] = '' 

O, si usted no sabe el índice:

i=lst.index[pattern] 
lst[i]='' 

o, si usted tiene una lista de listas y desea cambiar cada primer elemento de cada sublista:

for i, sublst in enumerate(lst): 
    if sublst[i][0] in patterns: sublist[i][0]='' 

etc, etc., etc.

Si desea aplicar algo a cada elemento de una lista, puede usar una lista de comprensión, un mapa o una de las muchas herramientas del kit de Python.

En lo personal, por lo general tienden a utilizar las listas por comprensión más para la creación de la lista:

l=[[ x for x in range(5) ] for y in range(4)] #init a list of lists... 

¿Qué es más natural que:

l=[] 
for i in range(4): 
    l.append([]) 
    for j in range(5): 
     l[i].append(j)  

Sin embargo, para modificar esa misma lista de listas, que es más ¿comprensible?

Este:

l=[['new value' if j==0 else l[i][j] for j in range(len(l[i]))] for i in range(len(l))] 

o esto:

for i,outter in enumerate(l): 
    l[i][0]='new value'    

YMMV

Here es un gran tutorial sobre esto.

+3

Y esto debería escribirse como 'si lst [0] en patrones: lst [0] = '''. –

+1

@Tim: ¡Envía eso como respuesta! No puedo creer que se me ocurrieran otras tres formas de hacerlo sin la obvia ... ;-) – Cameron

+0

@Tim Pietzcker: así lo escribiría, pero quería mostrar (mi interpretación) que él tenía esto dentro ... – dawg

4

En resumen: no es así. Las listas de comprensión son para generar listas, no modificar listas existentes. Si desea modificar una lista, use un ciclo for, ya que eso es para lo que son.

La forma Pythonic escribir ese código sería algo así como:

for pattern in start_pattern: 
    if lst[0] == pattern: 
     lst[0] = '' 
     #the following assumes that pattern will never be '' 
     #if that's possible, you can ignore this bit 
     break 

Sin embargo, si realmente, realmente quiere hacer dentro de una asignación, y no les importa todos los programadores de Python que alguna vez se ocupa de su código odiándolo por toda la eternidad, hay algunas funciones que se pueden utilizar:

  • Si la variable que desea asignar a un mundial, entonces usted puede hacer

    globals().update(var=value) 
    
  • Si la variable que desea asignar a una secuencia mutable o un mapa (como una lista o un diccionario)

    list.__setitem__(index, value) 
    
+0

La ruptura siempre es válida. Incluso si hay un '''' en los datos, solo va a hacer que 'lst [0]' se reasigne al mismo valor ... – Cameron

+0

A menos que lst sea un tipo de secuencia mutable donde la asignación de elementos se ha sobrecargado para realizar un seguimiento de cuántas veces se asignó un valor dado, o cualquier otro tipo de comportamiento no estándar. –

+0

Hmm, buen punto. Sin embargo, espero que sea una ocurrencia muy rara :-) – Cameron

7

lenguaje Python tiene conceptos distintos de expresiones y declaraciones.

Asignación es una declaración incluso si la sintaxis veces te engaña pensando que es una expresión (por ejemplo a=b=99 obras, pero es un caso especial de sintaxis y no significa que el b=99 es una expresión como es, por ejemplo, en C).

Las listas de comprensión son en su lugar expresiones porque devuelven un valor, en cierto sentido el bucle que realizan es un incidente y el punto principal es la lista devuelta.

Una instrucción puede contener expresiones pero una expresión no puede contener declaraciones.

Dicho esto, sin embargo, la asignación de elemento de lista a se convierte internamente en una llamada a método (para permitir la creación de objetos de tipo lista) y las llamadas a método son expresiones. Por lo tanto se puede técnicamente utiliza la asignación de lista de elementos en una expresión:

[ lst.__setitem__(0, '') for pattern in start_pattern if lst[0] == pattern ] 

Esto es sin embargo considerado malo porque perjudica la legibilidad y lo fácil que es leer el código fuente es el foco principal en el lenguaje Python. Usted debe escribir en su lugar, por ejemplo ...

for pattern in start_pattern: 
    if lst[0] == pattern: 
     lst[0] = '' 

que dicho sea de paso, gracias a que el operador in es equivalente a las aún más legibles

if lst[0] in start_pattern: 
    lst[0] = '' 

listas por comprensión se utilizan por su valor de retorno y hacen un bucle interno ... Si lo que quieres es el bucle, entonces solo escribe un bucle ... quien lea el código tratando de entender lo que hace lo apreciará mucho (y a quien te incluyas dentro de unas semanas).

Cuestiones relacionadas