Параметр инициализатора reduce() по сумме элементов итерируемого

#python-3.x

#python-3.x

Вопрос:

Запрос, касающийся этого кода:

 from functools import reduce

def sum_even(it):
    return reduce(lambda x, y: x   y if not y % 2 else x, it,0)
    
print(sum_even([1, 2, 3, 4]))
  

Почему бы не добавить третий параметр reduce() добавляет первый нечетный элемент списка?

Ответ №1:

Если вы не передаете начальный элемент явно, то первые два элемента ввода становятся аргументами для первого вызова редуктора, так x было бы 1 и y будет 2 . Поскольку ваш тест исключает только нечетные y s, а не x s, значение x сохраняется, и все будущие x s являются суммами, основанными на этом начальном 1 . Использование 0 в качестве явного начального значения означает только 0 и (позже), что накопленная сумма этого 0 и других четных чисел когда-либо передается как x , поэтому нечетное число никогда не передается как x .

Обратите внимание, что это довольно глупый способ сделать это. Гораздо проще построить эту операцию из частей, используя один инструмент для фильтрации по четности, а другой — для суммирования оставшихся элементов из операции фильтрации. Например:

 def sum_even(it):
    return sum(x for x in it if not x % 2)
  

короче, понятнее и (вероятно) быстрее, чем reduce вы написали.