Cuando ejecuto este código en Python 2.6

reduce(lambda x,y: x+[y], [1,2,3],[])

Obtengo [1, 2, 3] como se esperaba. Pero cuando ejecuto este (creo que es equivalente al anterior)

reduce(lambda x,y: x.append(y), [1,2,3],[])

Me sale un mensaje de error

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <lambda>
AttributeError: 'NoneType' object has no attribute 'append'

¿Por qué estas dos líneas de código no dan el mismo resultado?

12
Fedor Kotov 25 may. 2011 a las 16:40

4 respuestas

La mejor respuesta

x.append(y) no es equivalente a x+[y]; append modifica una lista en su lugar y no devuelve nada, mientras que x+[y] es una expresión que devuelve el resultado.

15
Wooble 25 may. 2011 a las 12:44

Se espera que el argumento de la función para reduce devuelva el resultado de la operación.

x+[y] hace eso, mientras que x.append(y) no (este último modifica x y devuelve None).

6
NPE 25 may. 2011 a las 12:43

Solo para explicar el mensaje de error:

AttributeError: 'NoneType' object has no attribute 'append'

La expresion

reduce(lambda x,y: x.append(y), [1,2,3],[])

Es equivalente a

[].append(1).append(2).append(3)

Como [].append(1) no devuelve un valor, es decir, devuelve None que intenta ejecutar (en el segundo paso)

None.append(2)

Que da como resultado el mensaje de error Nonetype object has no attribute append

0
phynfo 25 may. 2011 a las 14:45

reduce llama a la función y utiliza el valor de retorno como el nuevo resultado. append devuelve None y, por lo tanto, la siguiente invocación append falla. Podrías escribir

def tmpf(x,y):
   x.append(y)
   return x
reduce(tmpf, [1,2,3], [])

Y obtener el resultado correcto. Sin embargo, si el resultado es una lista del mismo tamaño que la entrada, no está buscando reducir: el resultado de la reducción generalmente debe ser un valor único. En su lugar, use mapa o simplemente

[x for x in [1,2,3]]
7
phihag 25 may. 2011 a las 12:52