2011-05-25 35 views
11

Cuando ejecuto el código en Python 2,6extraño reducir el comportamiento

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

consigo [1, 2, 3] como se esperaba. Pero cuando ejecuto este (creo que es equivalente a la 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?

Respuesta

14

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

+0

Gracias. Ahora veo que debería haber leído la documentación más atentamente. –

6

Se espera que el argumento de función reducedevuelva el resultado de la operación.

lo hace, mientras que x.append(y) no (este último modifica x y devuelve None).

7

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. Puede 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 reducir debería ser un valor único. En su lugar, utilice map o simplemente

[x for x in [1,2,3]] 
+2

no me definir 'tmpf' de esta manera, ya que tiene el efecto secundario inesperado de modificar el inicializador (último argumento para 'reducir'). – NPE

+0

@aix Se agregó una advertencia adicional contra el uso de 'reduce' para producir una lista. Puede insertar 'if len (x) == 0: x = []' en 'tmpf', pero eso solo subraya que' reduce' no es la herramienta adecuada para este trabajo. – phihag

0

Sólo para explicar el mensaje de error:

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

La expresión

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

es equivalente a

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

Desde [].append(1) no devuelve un valor, es decir, que vuelve None intenta ejecutar (en la segunda etapa)

None.append(2)

que resulta en el mensaje de error Nonetype object has no attribute append