Введение
Встроенная в Python функция map()
используется для применения функции к каждому элементу итерируемого объекта (например, списка или словаря) и возврата нового итератора для получения результатов. Функция map()
возвращает объект map (итератор), который мы можем использовать в других частях нашей программы. Также мы можем передать объект map в функцию list()
или другой тип последовательности для создания итерируемого объекта.
Функция map()
имеет следующий синтаксис:
map(function, iterable, [iterable 2, iterable 3, ...])
Вместо использования цикла for
функция map()
дает возможность применить функцию к каждому элементу итерируемого объекта. Это повышает производительность, поскольку функция применяется только к одному элементу за раз без создания копий элементов в другом итерируемом объекте. Это особенно полезно при обработке больших наборов данных. Также map()
может принимать несколько итерируемых объектов в качестве аргументов функции, отправляя в функцию по одному элементу каждого итерируемого объекта за раз.
В этом обучающем модуле мы рассмотрим три способа работы с map()
: с функцией lambda
, с определяемой пользователем функцией и со встроенной функцией, использующей несколько аргументов итерируемого объекта.
Использование функции Lambda
Первый аргумент map()
— это функция, которую мы используем для применения к каждому элементу. Python вызывает функцию один раз для каждого элемента итериируемого объекта, который мы передаем в map()
, и возвращает измененный элемент в объект map. В качестве первого аргумента функции мы можем передать определенную пользователем функцию или использовать функции lambda
, особенно если выражение будет менее сложным.
Синтаксис map()
с функцией lambda выглядит следующим образом:
map(lambda item: item[] expression, iterable)
С таким списком мы можем реализовать функцию lambda
с выражением, которое хотим применить к каждому элементу в нашем списке:
numbers = [10, 15, 21, 33, 42, 55]
Чтобы применить выражение к каждому из наших чисел, мы можем использовать map()
и lambda
:
mapped_numbers = list(map(lambda x: x * 2 + 3, numbers))
Здесь мы декларируем элемент в нашем списке как x
. Затем мы добавим наше выражение. Мы передадим список чисел как итерируемый объект для map()
.
Для немедленного получения результатов мы распечатаем список объекта map
:
print(mapped_numbers)
Output
[23, 33, 45, 69, 87, 113]
Мы использовали list()
, чтобы объект map был выведен как список, а не в трудной для интерпретации объектной форме, например: <map object at 0x7fc250003a58>
. Объект map является итератором наших результатов, чтобы мы могли использовать его в цикле for
или использовать list()
для превращения в список. Мы делаем это здесь, потому что это хороший способ просмотра результатов.
В итоге map()
наиболее полезна для работы с большими наборами данных, чтобы мы могли работать с объектом map, и не использовали для них конструктор, например, list()
.
Для небольших наборов данных список может быть более понятным, однако для этого обучающего модуля мы используем небольшой набор данных для демонстрации возможностей map()
.
Реализация определяемой пользователем функции
Аналогично lambda
мы можем использовать определенную функцию для применения к итерируемому объекту. Функции lambda
более полезны при использовании выражения с одной строкой, определяемые пользователем функции лучше подходят для более сложных выражений. Если же нам нужно передать в функцию другой элемент данных, применяемый к итерируемому объекту, определяемые пользователем функции будут удобнее для чтения.
Например, в следующем итерируемом объекте каждый элемент является словарем, содержащим различные детали о каждом из существ в нашем аквариуме:
aquarium_creatures = [
{"name": "sammy", "species": "shark", "tank number": 11, "type": "fish"},
{"name": "ashley", "species": "crab", "tank number": 25, "type": "shellfish"},
{"name": "jo", "species": "guppy", "tank number": 18, "type": "fish"},
{"name": "jackie", "species": "lobster", "tank number": 21, "type": "shellfish"},
{"name": "charlie", "species": "clownfish", "tank number": 12, "type": "fish"},
{"name": "olly", "species": "green turtle", "tank number": 34, "type": "turtle"}
]
Мы решили, что все существа в аквариуме будут перемещены в один и тот же резервуар. Нам нужно обновить наши записи, чтобы показать, что все наши существа перемещаются в резервуар 42
. Чтобы дать map()
доступ к каждому словарю и каждой паре ключ:значение в словарях, мы построим вложенную функцию:
def assign_to_tank(aquarium_creatures, new_tank_number):
def apply(x):
x["tank number"] = new_tank_number
return x
return map(apply, aquarium_creatures)
Мы определяем функцию assign_to_tank()
, которая принимает aquarium_creatures
и new_tank_number
в качестве параметров. В assign_to_tank()
мы передаем apply()
как функцию в map()
в последней строке. Функция assign_to_tank
возвратит iterator, полученный от map()
.
apply()
принимает в качестве аргумента x
, что означает элемент в нашем списке — одиночный словарь.
Далее мы указываем, что x
— это ключ "tank number"
из aquarium_creatures
, и что он должен хранить переданное значение new_tank_number
. Мы возвратим каждый элемент после применения нового номера резервуара.
Мы вызовем assign_to_tank()
с нашим списком словарей и новый номер резервуара, который нам нужно заменить для каждого существа:
assigned_tanks = assign_to_tank(aquarium_creatures, 42)
После выполнения функции мы сохраним объект фильтра в переменной assigned_tanks
, которую мы превратим в список и распечатаем:
print(list(assigned_tanks))
Вывод программы будет выглядеть следующим образом:
Output
[{'name': 'sammy', 'species': 'shark', 'tank number': 42, 'type': 'fish'}, {'name': 'ashley', 'species': 'crab', 'tank number': 42, 'type': 'shellfish'}, {'name': 'jo', 'species': 'guppy', 'tank number': 42, 'type': 'fish'}, {'name': 'jackie', 'species': 'lobster', 'tank number': 42, 'type': 'shellfish'}, {'name': 'charlie', 'species': 'clownfish', 'tank number': 42, 'type': 'fish'}, {'name': 'olly', 'species': 'green turtle', 'tank number': 42, 'type': 'turtle'}]
Мы присвоили новый номер резервуара нашему списку словарей. Используя функцию, которую мы определяем, мы включаем map()
для эффективного применения функции к каждому элементу списка.
Использование встроенной функции с несколькими итерируемыми объектами
Помимо функций lambda
и определяемых нами функций, мы можем использовать вместе с map()
встроенные функции Python. Для применения функции с несколькими итерируемыми объектами мы передаем имя другого итерируемого объекта после первого. Рассмотрим в качестве примера функцию pow()
, которая принимает два числа и возводит базовое число в указанную степень.
Здесь у нас списки целых чисел, которые мы хотим использовать с pow()
:
base_numbers = [2, 4, 6, 8, 10]
powers = [1, 2, 3, 4, 5]
Затем мы передадим pow()
в качестве функции в map()
и укажем два списка в качестве итерируемых объектов:
numbers_powers = list(map(pow, base_numbers, powers))
print(numbers_powers)
map()
применит функцию pow()
к тому же элементу в каждом списке для возведения в степень. Поэтому в результатах мы увидим 2**1
, 4**2
, 6**3
и т. д.:
Output
[2, 16, 216, 4096, 100000]
Если мы передадим map()
итерируемый объект, который будет длиннее другого итерируемого объекта, map()
остановит расчеты после достижения конца наиболее короткого объекта. В следующей программе мы дополним base_numbers
тремя дополнительными числами:
base_numbers = [2, 4, 6, 8, 10, 12, 14, 16]
powers = [1, 2, 3, 4, 5]
numbers_powers = list(map(pow, base_numbers, powers))
print(numbers_powers)
В расчетах программы ничего не изменится, и результат будет точно таким же:
Output
[2, 16, 216, 4096, 100000]
Мы использовали функцию map()
со встроенной функцией Python и посмотрели на одновременную обработку нескольких итерируемых объектов. Мы увидели, что map()
продолжит обрабатывать несколько итерируемых объектов, пока не достигнет конца объекта, содержащего меньше всего элементов.
Заключение
В этом обучающем модуле мы узнали о различных способах использования функции map()
в Python. Теперь вы можете использовать map()
с собственной функцией, с функцией lambda
и с любыми другими встроенными функциями. Также вы можете реализовать map()
с функциями, для которых требуется несколько итерируемых объектов.
В этом обучающем модуле мы распечатали результаты map()
в формате списка для демонстрационных целей. В наших программах мы обычно будем использовать возвращаемый объект map для дальнейших манипуляций с данными.
Для получения дополнительной информации о Python ознакомьтесь с нашей серией Программирование на Python 3 и посетите нашу тематическую страницу, посвященную Python. Чтобы узнать больше о работе с наборами данных в функциональном программировании, читайте нашу статью о функции filter()
.