map (), filter () и reduce () в Python с примерами

Введение Функции map (), filter () и reduce () привносят в Python немного функционального программирования. Все три из них являются удобными функциями, которые могут быть заменены на List Computing [/ list-complationions-in-python /] или циклы, но обеспечивают более элегантный и краткий подход к некоторым проблемам. Прежде чем продолжить, мы рассмотрим несколько вещей, с которыми вам следует ознакомиться, прежде чем читать о вышеупомянутых методах:> Что такое анонимная функция / метод или лямбда? Аноним

Вступление

Функции map() , filter() и reduce() привносят в Python немного функционального программирования. Все три из них являются удобными функциями, которые могут быть заменены списками или циклами, но обеспечивают более элегантный и краткий подход к некоторым проблемам.

Прежде чем продолжить, мы рассмотрим несколько вещей, с которыми вам следует ознакомиться, прежде чем читать о вышеупомянутых методах:

Что такое анонимная функция / метод или лямбда?

Анонимный метод - это метод без имени, то есть не привязанный к идентификатору, как когда мы определяем метод с помощью def method:

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

Каков синтаксис лямбда-функции (или лямбда-оператора)?

 lambda arguments: expression 

Думайте о лямбдах как о однострочных методах без имени. Они работают практически так же, как и любой другой метод в Python, например:

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

Может быть переведен на:

 lambda x, y: x + y 

Лямбда-выражения отличаются от обычных методов Python, потому что они могут иметь только одно выражение, не могут содержать никаких операторов, а их возвращаемый тип - объект function Таким образом, приведенная выше строка кода возвращает не значение x + y а функцию, которая вычисляет x + y .

Почему лямбда-выражения имеют отношение к map() , filter() и reduce() ?

Все три метода ожидают, что в качестве первого аргумента будет объект function Этот function объект может быть предопределенным методом с именем (например, def add(x,y) ).

Хотя чаще всего функции, переданные в map() , filter() и reduce() , используются только один раз, поэтому часто нет смысла определять функцию, на которую можно ссылаться.

Чтобы избежать определения новой функции для различных map() / filter() / reduce() - более элегантным решением будет использование короткой одноразовой анонимной функции, которую вы будете использовать только один раз и никогда больше - лямбда.

Функция map ()

Функция map() выполняет итерацию по всем элементам в данной итерации и выполняет function мы передали в качестве аргумента для каждого из них.

Синтаксис:

 map(function, iterable(s)) 

Мы можем передать столько итерируемых объектов, сколько захотим, после передачи function которую хотим использовать:

 # Without using lambdas 
 def starts_with_A(s): 
 return s[0] == "A" 
 
 fruit = ["Apple", "Banana", "Pear", "Apricot", "Orange"] 
 map_object = map(starts_with_A, fruit) 
 
 print(list(map_object)) 

Этот код приведет к:

 [True, False, False, True, False] 

Как мы видим, мы получили новый список, в котором функция starts_with_A() оценивалась для каждого элемента в списке fruit . Результаты этой функции добавлялись в список последовательно.

Более красивый способ сделать то же самое - использовать лямбды:

 fruit = ["Apple", "Banana", "Pear", "Apricot", "Orange"] 
 map_object = map(lambda s: s[0] == "A", fruit) 
 
 print(list(map_object)) 

Получаем тот же результат:

 [True, False, False, True, False] 

Примечание: вы могли заметить, что мы map_object к списку для печати значения каждого элемента. Мы сделали это, потому что вызов print() в списке распечатает фактические значения элементов. Вызов print() для map_object этого распечатает адреса памяти значений.

Функция map() возвращает map_object , который является итерируемым, и мы также могли бы напечатать такие результаты:

 for value in map_object: 
 print(value) 

Если вы хотите, чтобы map() вместо этого возвращала список, вы можете просто преобразовать его при вызове функции:

 result_list = list(map(lambda s: s[0] == "A", fruit)) 

Функция filter ()

Подобно map() , filter() принимает function и итерацию и создает новый список.

Как следует из названия, filter() формирует новый список, содержащий только элементы, удовлетворяющие определенному условию, то есть переданная function True .

Синтаксис:

 filter(function, iterable(s)) 

Используя предыдущий пример, мы видим, что новый список будет содержать только элементы, для которых starts_with_A() возвращает True :

 # Without using lambdas 
 def starts_with_A(s): 
 return s[0] == "A" 
 
 fruit = ["Apple", "Banana", "Pear", "Apricot", "Orange"] 
 filter_object = filter(starts_with_A, fruit) 
 
 print(list(filter_object)) 

Выполнение этого кода приведет к сокращению списка:

 ['Apple', 'Apricot'] 

Или переписать с использованием лямбды:

 fruit = ["Apple", "Banana", "Pear", "Apricot", "Orange"] 
 filter_object = filter(lambda s: s[0] == "A", fruit) 
 
 print(list(filter_object)) 

Печать дает нам тот же результат:

 ['Apple', 'Apricot'] 

Функция reduce ()

reduce() работает иначе, чем map() и filter() . Он не возвращает новый список на основе function и итерации. Вместо этого он возвращает одно значение.

Кроме того, в Python 3 reduce() больше не является встроенной функцией, и ее можно найти в модуле functools

Синтаксис:

 reduce(function, sequence[, initial]) 

reduce() работает, вызывая function мы передали для первых двух элементов в последовательности. Результат, возвращаемый function , используется в другом вызове function вместе со следующим (в данном случае третьим) элементом.

Этот процесс повторяется, пока мы не пройдем все элементы последовательности.

Необязательный аргумент initial используется, если он присутствует, в начале этого «цикла» с первым элементом в первом вызове function . В некотором смысле, initial элемент - это 0-й элемент перед первым, если он указан.

reduce() немного сложнее для понимания, чем map() и filter() , поэтому давайте рассмотрим пошаговый пример:

  1. Мы начинаем со списка [2, 4, 7, 3] и передаем функцию add(x, y) reduce() вместе с этим списком без initial значения.

  2. reduce() вызывает add(2, 4) , а add() возвращает 6

  3. reduce() вызывает add(6, 7) (результат предыдущего вызова add() и следующий элемент в списке в качестве параметров), а add() возвращает 13

  4. reduce() вызывает add(13, 3) , а add() возвращает 16

  5. Поскольку в последовательности больше не осталось элементов, reduce() возвращает 16

Единственная разница, если бы мы указали initial значение, был бы дополнительный шаг - 1,5. где reduce() вызовет add(initial, 2) и будет использовать это возвращаемое значение на шаге 2 .

Давайте продолжим и воспользуемся функцией reduce()

 from functools import reduce 
 
 def add(x, y): 
 return x + y 
 
 list = [2, 4, 7, 3] 
 print(reduce(add, list)) 

Выполнение этого кода даст:

 16 

Опять же, это можно было бы написать с помощью лямбда-выражений:

 from functools import reduce 
 
 list = [2, 4, 7, 3] 
 print(reduce(lambda x, y: x + y, list)) 
 print("With an initial value: " + str(reduce(lambda x, y: x + y, list, 10))) 

И код приведет к:

 16 
 With an initial value: 26 

Заключение

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

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

Если вы поймали себя на том, что пытаетесь уместить необходимую логику в одну map() или одно лямбда-выражение, гораздо лучше просто написать немного более длинный метод for-loop / defined и избежать ненужной путаницы в дальнейшем.

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus

Содержание