Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Знакомство с map, filter и reduce Python: Функции

Функции высшего порядка map, filter и reduce — это наиболее распространенные и мощные инструменты в программировании. Они позволяют работать с коллекциями данных. Эти функции упрощают и ускоряют работу с данными, позволяют писать более чистый и эффективный код.

В этом уроке мы рассмотрим подробно каждую из этих функций и научимся применять их в практических задачах.

Map

Допустим, мы хотим применить к каждому элементу списка чисел функцию или операцию. Мы можем использовать цикл for, чтобы пройтись по элементам списка и применить операции к каждому элементу.

Например, у нас есть список чисел. Мы хотим получить новый список, в котором каждый элемент будет возводиться в квадрат, а затем вычитаться десять. Мы можем решить эту задачу через цикл:

numbers = [1, 2, 3, 4, 5]
new_numbers = []
for num in numbers:
    squared = num ** 2
    subtracted = squared - 10
    new_numbers.append(subtracted)

print(new_numbers)
# [-9, -6, -1, 6, 15]

У такого подхода есть недостатки: код становится громоздким, трудно читаемым и поддерживаемым.

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

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

Рассмотрим реализацию функции map:

def map(func, iterable):
    result = []
    for item in iterable:
        result.append(func(item))
    return result

Этот цикл похож на цикл из примера выше. Здесь мы создаем пустой список result и затем циклом проходимся по элементам переданного итерируемого объекта iterable. Для каждого элемента мы вызываем функцию func и добавляем ее результат в список result. По завершении цикла мы возвращаем список result.

Теперь попробуем применить функцию map к нашей задаче:

def process_number(num):
    squared = num ** 2
    subtracted = squared - 10
    return subtracted

numbers = [1, 2, 3, 4, 5]
new_numbers = map(process_number, numbers)

print(new_numbers)
# [-9, -6, -1, 6, 15]

В данном примере мы сначала определили функцию process_number, которую хотим применить к каждому элементу списка. Далее передали ее со списком numbers в функцию map.

Функция map позволила нам более эффективно и лаконично обработать коллекцию данных. Она применила функцию к каждому элементу коллекции и вернула новый список с преобразованными значениями.

Далее рассмотрим функцию filter.

Filter

Часто в программировании нужно отфильтровать коллекцию данных — то есть выбрать из коллекции только те элементы, которые удовлетворяют определенным условиям.

Например, если у нас есть список чисел и мы хотим получить только те, которые больше пяти, то мы можем использовать цикл for, чтобы пройтись по элементам списка и проверить условия для каждого элемента:

numbers = [2, 7, 1, 8, 4, 5]
result = []
for num in numbers:
    if num > 5:
        result.append(num)

print(result)
# [7, 8]

При этом у такого подхода тоже есть свои недостатки: код становится громоздким и трудночитаемым.

В этом случае можно воспользоваться функцией filter. Она позволяет отфильтровать элементы коллекции на основе заданного условия и вернуть новую коллекцию с элементами, которые удовлетворяют этому условию. Многие языки имеют аналогичную функцию с тем же именем.

Реализация функции filter аналогична реализации функции map:

def filter(func, iterable):
    result = []
    for item in iterable:
        if func(item):
            result.append(item)
    return result

Здесь мы создаем пустой список result и затем циклом проходимся по элементам переданного итерируемого объекта iterable. Для каждого элемента мы вызываем функцию func и проверяем, удовлетворяет ли он заданному условию. Если условие выполняется, то мы добавляем элемент в список result. По завершении цикла мы возвращаем список result.

Теперь рассмотрим пример использования функции filter. Допустим, у нас есть список чисел, и мы хотим получить только те числа, которые больше пяти:

def greater_than_five(num):
    return num > 5

numbers = [2, 7, 1, 8, 4, 5]
result = filter(greater_than_five, numbers)

print(result)
# [7, 8]

Здесь мы сначала определили функцию greater_than_five, которая возвращает True, если переданный ей аргумент больше пяти. Далее передали ее со списком numbers в функцию filter.

Так функция filter упростила код и повысила его читаемость и дальнейшее сопровождение.

Теперь рассмотрим функцию reduce.

Reduce

Последняя функция из нашей тройки — reduce() (говорят "свертка"), который используется для агрегации данных. Под агрегацией понимается операция, вычисляющая значение, зависящее от всего набора данных. С помощью функции reduce можно последовательно применить операции к элементам списка, чтобы получить единственное значение. Допустим, у нас есть список чисел, и мы хотим получить их сумму. В этом случае мы можем использовать цикл for, чтобы последовательно складывать каждый элемент списка. Например:

numbers = [1, 2, 3, 4, 5]
result = 0
for num in numbers:
    result += num

print(result)
# 15

В данном примере мы объявляем переменную result и присваиваем значение 0. Затем циклом for проходим по всем элементам списка numbers. Каждый элемент списка numbers прибавляем к значению переменной result. После завершения цикла в переменной result у нас хранится сумма всех элементов списка numbers.

Теперь рассмотрим пример, когда нам нужно перемножить все элементы в списке. Мы также можем решить эту задачу через цикл:

numbers = [1, 2, 3, 4, 5]
result = 1
for num in numbers:
    result *= num

print(result)
# 120

Здесь у нас код похож на сложение всех элементов списка. Отличие — начальное значение переменной result и операция, которую мы выполняем.

Теперь улучшим код для этих двух примеров. Воспользуемся функцией reduce, которая позволяет последовательно применять операцию к элементам списка, возвращая единственное значение.

Рассмотрим реализацию функции reduce:

def reduce(func, iterable, initial):
    result = initial
    for item in iterable:
        result = func(result, item)
    return result

В данном примере на вход функции reduce передаются три аргумента:

  • func — функция, которую мы будем применять к элементам iterable
  • iterable — итерируемый объект, элементы которого мы будем обрабатывать функцией func
  • initial — начальное значение, которое будет использоваться при первом вызове функции func

Внутри функции создаем переменную result, которой в качестве начального значения передаем значение initial. Затем циклом for проходим по всем элементам объекта iterable и каждый элемент вместе со значением result передаем в функцию func. Результат функции func записываем в переменную result. Результатом работы функции reduce будет финальное значение переменной result.

Теперь рассмотрим пример использования функции reduce, чтобы найти сумму и произведение элементов списка:

def add(x, y):
    return x + y

def multiply(x, y):
    return x * y

numbers = [1, 2, 3, 4, 5]
result = reduce(add, numbers, 0)
print(result)
# 15

result = reduce(multiply, numbers, 1)
print(result)
# 120

Здесь мы создали две функции add и multiply, чтобы сложить и перемножить два числа. Далее мы используем функцию reduce, чтобы получить результат применения функций add и multiply к элементам списка numbers.

При первом вызове функции reduce мы передаем начальное значение 0, а при втором вызове — значение 1. Так нам удалось сократить и сделать более читаемый код.

Map, filter и reduce против цикла for

Мы можем реализовать любую логику в цикле for, но этот инструмент не всегда удобный или понятный. Например, если нам нужно преобразовать каждый элемент списка, то использование цикла for может вызвать проблемы с читаемостью кода и его поддержкой в будущем.

В этом случае мы можем воспользоваться функцией map, которая позволяет применить функцию к каждому элементу списка и вернуть новый список с преобразованными значениями. Также для выбора элементов по определенному условию вместо цикла for можно использовать функцию filter, которая вернет элементы, удовлетворяющие заданному условию.

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

Цикл не всегда можно заменить на функции map, filter или reduce. Но если речь идет о простых манипуляциях со списками, то использование этих функций может значительно упростить чтение, написание и понимание кода. Еще это помогает избежать ошибок в логике и сделать код более читаемым и поддерживаемым в будущем, так как каждая функция делает одну работу.

Выводы

В этом уроке мы рассмотрели три функции: map, filter и reduce. Это более простой и лаконичный способ выполнить операции, которые могут быть выполнены также с помощью цикла for.

Эти функции могут быть менее мощными, чем цикл for, и не позволяют выполнить такое разнообразное количество операций. Но они делают код более лаконичным, удобочитаемым и предсказуемым. Использование этих функций может упростить написание и понимание кода, особенно, при работе с большими объемами данных.

При этом в сложных случаях, когда нужно изменить состояние объектов или выполнять некоторые специфичные операции, цикл for может оставаться предпочтительным. Поэтому при выборе способа решения задачи всегда нужно учитывать особенности конкретной задачи и выбирать наиболее подходящий инструмент для ее решения.


Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Об обучении на Хекслете

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
от 6 300 ₽ в месяц
Разработка веб-приложений на Django
10 месяцев
с нуля
Старт 25 апреля

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»