Короткий ответ
map(), filter() и reduce() — функции для функциональной обработки коллекций. map() применяет функцию к каждому элементу, filter() отбирает элементы по заданному условию, а reduce() последовательно сводит коллекцию к одному итоговому значению.
Как это работает подробнее
В Python 3 map() и filter() возвращают итераторы, поэтому результат обычно оборачивают в list(), а reduce() вынесена в модуль functools.
- Преобразование.
map(func, iterable)вызывает функцию для каждого элемента и возвращает итератор с результатами; в качестве функции часто передают лямбду. - Фильтрация.
filter(predicate, iterable)оставляет только те элементы, для которых функция-предикат вернула истину. - Свёртка.
reduce(func, iterable)из модуляfunctoolsпоследовательно комбинирует элементы — например, суммирует их или находит максимум за один проход. - Ленивость. Итераторы, возвращаемые
map()иfilter(), вычисляются по требованию, что экономит память при обработке больших последовательностей.
Пример кода
Совместное использование трёх функций
from functools import reduce
numbers = [1, 2, 3, 4]
# map: умножаем каждый элемент на 2
print(list(map(lambda x: x * 2, numbers))) # [2, 4, 6, 8]
# filter: оставляем только чётные
print(list(filter(lambda x: x % 2 == 0, numbers))) # [2, 4]
# reduce: складываем все элементы
print(reduce(lambda x, y: x + y, numbers)) # 10Что использовать на практике
- Comprehensions. Вместо
map()иfilter()чаще используют включения:[x * 2 for x in numbers]и[x for x in numbers if x % 2 == 0]читаются лучше. - Несколько коллекций.
map()умеет принимать несколько итерируемых объектов и передавать их элементы в функцию по очереди. - Свёртка данных.
reduce()полезна, когда нужно свести коллекцию к одному значению, — например, вычислить произведение всех элементов. - Большие данные. Благодаря ленивости итераторов связки с
map()иfilter()не строят промежуточные списки целиком.
Подводные камни
- Забытый list(). В Python 3
map()иfilter()возвращают итератор, а не список, поэтому безlist()результат нельзя ни вывести, ни проиндексировать. - Разовый обход. Итератор можно использовать только один раз: повторное преобразование в список вернёт пустой список.
- Импорт reduce. В отличие от
map()иfilter(),reduce()не встроена — безfrom functools import reduceкод упадёт с ошибкой имени. - Читаемость лямбд. Длинная лямбда внутри
reduce()быстро становится нечитаемой, поэтому для сложной логики лучше именованная функция.
Как отвечать на собеседовании
- Перечисли назначение всех трёх функций: преобразование, фильтрация и свёртка → покажи пример с лямбдами на одном списке → отметь, что
map()иfilter()возвращают итераторы, аreduce()живёт в модулеfunctools→ добавь, что на практике их часто заменяют включениями.