Странное снижение поведения

Когда я выполняю этот код в python 2.6

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

Я получаю [1, 2, 3], как и ожидалось. Но когда я выполняю этот (я думаю, что это эквивалентно предыдущему)

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

Я получаю сообщение об ошибке

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

Почему эти две строки кода не дают одинакового результата?

Ответ 1

x.append(y) не эквивалентен x+[y]; append изменяет список на месте и ничего не возвращает, а x+[y] - это выражение, которое возвращает результат.

Ответ 2

reduce вызывает функцию и использует возвращаемое значение в качестве нового результата. append возвращает None, и поэтому следующий вызов append завершается с ошибкой. Вы можете написать

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

и получите правильный результат. Однако, если результатом является список того же размера, что и вход, вы не ищете сокращения: результат сокращения обычно должен быть единственным значением. Вместо этого используйте map или просто

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

Ответ 3

Ожидается, что аргумент функции reduce вернет результат операции.

x+[y] делает это, тогда как x.append(y) не делает (последний изменяет x и возвращает None).

Ответ 4

Только для объяснения сообщения об ошибке:

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

Выражение

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

эквивалентно

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

Так как [].append(1) не возвращает значение, то есть возвращает None, он пытается выполнить (на втором шаге)

None.append(2)

в результате чего появляется сообщение об ошибке Nonetype object has no attribute append