2010-03-24 9 views
12

Tengo una lista de, digamos, a = [[1,2],[3,4],[5,6]]Al añadir el artículo a listas dentro de una lista por comprensión

Quiero añadir la cadena 'a' a cada elemento de la lista a.

Cuando uso:

a = [x.append('a') for x in a] 

se devuelve [None,None,None].

Pero si uso:

a1 = [x.append('a') for x in a] 

entonces se hace algo extraño.

a, pero no a1 es [[1,2,'a'],[3,4,'a'],[5,6,'a']].

No entiendo por qué la primera llamada devuelve [None, None, None] ni por qué la segunda cambia en a en lugar de a1.

Respuesta

7

Para el primer caso, la razón por la que devuelve [None, None, None] es porque la función list.append devuelve None, y eso es lo que almacena en la lista.

En el segundo caso, es porque la lista es mutable, y cada vez que agrega el valor, la lista original se modifica.

Lo que necesita es un operador de anexo no en el lugar, como +. es decir, [x + ['a'] for x in a].

23

list.append muta la lista y devuelve None. Las listas de comprensión son para almacenar el resultado, que no es lo que desea en este caso si solo quiere cambiar las listas originales.

>>> x = [[1, 2], [3, 4], [5, 6]] 
>>> for sublist in x: 
...  sublist.append('a') 
... 
>>> x 
[[1, 2, 'a'], [3, 4, 'a'], [5, 6, 'a']] 
3

(Esta es una combinación de las respuestas de Mike Graham y sykora):

Si solamente desea cambiar los valores en el lugar, tratar un habitual de bucle, y no una lista por comprensión :

for sublist in a: 
    sublist.append('a') 

Si desea dejar un solo, y poner el resultado en A1:

a1 = [sublist + ['a'] for sublist in a] 

a medida que se explicado, append modifica la lista, pero devuelve None, mientras que + deja la lista solo, pero devuelve una lista nueva y anexa.

+3

Debe ser a1 = [sublista + ['a'] para la sublista en a]. Observe los corchetes alrededor de 'a'. –

+0

Whoops. Fijo. Gracias. – Oddthinking

0

abandonan el a = y utilizar el efecto secundario de a:

[x.append('a') for x in a] 
print a 
+2

Por favor, no. Tirar una lista de comprensión solo para utilizar sus efectos secundarios es mala forma; su sugerencia funciona, pero está mal visto al igual que el uso similar del 'mapa 'ha sido mal visto. Explícito es mejor que implícito; use un ciclo en lugar de una lista de comprensión. – tzot

6

Como han dicho otros, append muta la propia lista y no debe asignar a una variable. Ejecutarlo cambia sus datos, actualizando efectivamente a todos los que lo señalan.

Pero, hay un truco que utilizo cuando quiero hacer cosas de una manera funcional *, mientras que la mutación de objetos existentes (en lugar de construir otros nuevos, en este caso utilizando a=[x + ['a'] for x in a], o específicamente el x + ['a']).

lo tanto, si usted es lo suficientemente valiente también puede hacer esto:

>>> a=[[1,2],[3,4],[5,6]] 
>>> a=[x.append('a') or x for x in a] 
>>> a 
[[1, 2, 'a'], [3, 4, 'a'], [5, 6, 'a']] 

Esto funciona porque append vuelve None, y el or continúa en la búsqueda de un valor de verdad-y, lo que es x (es un list con al menos lo que se adjuntó).

¿Por qué incluso necesito esto?

Digamos que tienes una lista y que desea insertar algunos de sus miembros a una nueva lista, y actualizar las referencias en consecuencia:

Así que tienes la lista all:

>>> all = [[], [], [], []] 

Algunos de que se inserta y se actualiza a una nueva lista x:

>>> x = [i.append('x') or i for i in all[:2]] 
>>> x 
[['x'], ['x']] 

Algunos de all también se inserta yu pdated a una lista y:

>>> y = [i.append('y') or i for i in all[1:3]] 

all se actualiza:

>>> all 
[['x'], ['x', 'y'], ['y'], []] 

Pero x también se actualiza: se genera

>>> x 
[['x'], ['x', 'y']] 

Y y como se esperaba:

>>> y 
[['x', 'y'], ['y']] 

En general, para tareas simples, recomiendo usar un bucle for actualizando de forma explícita. Esto es lo que se considera pitónico.

Técnicamente hablando, si tuviera acceso a la clase de lista, puede hacer esta función:

def more_functional_append(self, x): 
    self.append(x) 
    return self 
  • functional programming se basa en cada declaración que hace esencialmente una cosa, y no tener efectos secundarios (por lo , no mutando y regresando). append no es muy funcional ya que muta una lista (la programación funcional pura solo tiene objetos inmutables) y no devuelve un resultado para pasar a otras acciones (funciones). Utilizando conceptos de programación funcional, puede crear ideas geniales que nadie puede leer, también conocidas como "seguridad laboral" o "código incorrecto".
+0

Tengo una opinión diferente sobre esta respuesta hoy en día, así que si está leyendo esto, por favor coméntelo para poder actualizarlo. Aquí falta una característica central para la programación funcional, que es la inmutabilidad y debería ampliarla. –

1

Puede usar la suma lista dentro de una lista por comprensión, así:

a = [x + [ 'a'] para x en a]

Esto le da al desear resultado para a. Uno podría hacerlo más eficiente en este caso asignando ['a'] a un nombre de variable antes del bucle, pero depende de lo que quiera hacer.

0

En la primera asignación de valor de su lista de comprensión un error de atributo, el objeto 'NoneType' no tiene atributo 'append', ayuda a explicar por qué su lista, a, se cargará con None (s). Para hacer que mi consola arrojara el error, utilicé x como una variable para la comprensión de la lista y también como el iterador.

Traceback (most recent call last): 
x = [x.append('a') for x in a] 
AttributeError: 'NoneType' object has no attribute 'append' 

Luego, volví a a para x y arrojó el mismo error.

Traceback (most recent call last): 
a = [x.append('a') for x in a] 
AttributeError: 'NoneType' object has no attribute 'append' 
Cuestiones relacionadas