Как работает функция map() в Python

В Python есть встроенная функция map(), которая позволяет применить заданную функцию к каждому элементу в итерируемом объекте (например, в списке или словаре) и возвращает новый итератор для извлечения результатов. Она возвращает объект map (или итератор), который затем можно использовать в других частях кода этой программы. Кроме того, объект map также можно передать в функцию list() и т.п., чтобы получить итерируемый объект.

Синтаксис функции map() выглядит следующим образом:

map(function, iterable, [iterable 2, iterable 3, ...])

Читайте также: Циклы for в Python 3

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

Данный мануал расскажет о трех способах применения функции map(): с лямбда-функцией, с пользовательской функцией и со встроенной функцией, которая использует несколько итерируемых аргументов.

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

Как говорилось ранее, первый аргумент функции map() – это та функция, которую мы хотим применить к каждому элементу итерируемого объекта. Python вызывает эту функцию для каждого элемента один раз, а затем передает их в map() и возвращает полученный элемент в виде map объекта. В качестве первого аргумента map() мы можем передать либо пользовательскую функцию, либо лямбда-функцию (особенно если выражение не очень сложное).

Синтаксис функции map() с лямбда-функцией имеет следующий вид:

map(lambda item: item[] expression, iterable)

Предположим, у нас есть приведенный ниже список.

numbers = [10, 15, 21, 33, 42, 55]

В таком случае мы можем использовать лямбда-функцию с выражением, которое мы хотим применить к каждому элементу в этом списке. Чтобы сделать это, мы можем использовать функции map() и lambda следующим образом:

mapped_numbers = list(map(lambda x: x * 2 + 3, numbers))

Здесь мы объявляем элемент списка как x, после чего добавляем выражение. Затем мы передаем список чисел функции map() как итерируемый объект.

Чтобы сразу получить результат, мы выводим полученный объект на экран:

print(mapped_numbers)
[23, 33, 45, 69, 87, 113]

Итак, мы использовали функцию list(), чтобы вывести map объект в виде списка, а не другого, менее удобочитаемого объекта типа <map object at 0x7fc250003a58>. Объект map – итератор результатов, поэтому его можно перебрать с помощью цикла for или использовать функцию list(), чтобы преобразовать его в список. Кроме того, в данном случае это хороший способ оценить результат.

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

Более подходящим вариантом для работы с небольшими наборами данных могут быть генераторы списков.

Как работает функция map() с пользовательской функцией

По аналогии с лямбда-функцией, мы можем применить к итерируемому объекту пользовательскую функцию. Лямбда-функции более полезны в работе с однострочными выражениями, а пользовательские функции – с более сложными. Более того, пользовательские функции позволяют сохранить удобочитаемость кода в тех случаях, когда вам нужно передать функции, которую вы применяете к своему итерируемому объекту, другой фрагмент данных.

Например, в следующем итерируемом объекте каждый элемент представляет собой словарь, который содержит сведения об одной конкретной рыбе из нашего аквариума (допустим, у вас есть аквариум).

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 вернет итератор, полученный в результате выполнения map().

Функция apply() в качестве аргумента принимает x, который представляет один элемент в списке (в нашем случае это один отдельно взятый словарь).

Затем мы определяем, что x соответствует ключу “tank number” из aquarium_creatures и что он должен сохранять переданные данные в new_tank_number. Функция возвращает каждый элемент после внесения в него нового номера резервуара.

Давайте вызовем функцию assign_to_tank() со списком словарей и номером нового резервуара, который нужно внести в сведения о каждом жителе аквариума:

assigned_tanks = assign_to_tank(aquarium_creatures, 42)

После выполнения функции мы получим map объект, хранящийся в переменной assign_tanks, которую мы преобразуем в список и выведем на экран:

print(list(assigned_tanks))

Этот код вернет следующий результат:

[{'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() и пользовательской функции. Подобным образом мы можем включить map() в код любой программы для эффективного применения функции к каждому элементу списка.

Функция map() и встроенная функция с несколькими

Как говорилось в начале мануала, в функции map() мы можем использовать встроенные функции Python. Чтобы применить функцию с несколькими итерируемыми объектами, нужно передать несколько имен объектов (одно за другим). Например, с помощью функции pow(), которая принимает два числа, можно возвести основное число в указанную степень.

Читайте также: Встроенные функции Python 3 для работы с числами

Предположим, у нас есть списки целых чисел, которые мы хотели бы использовать с функцией pow():

base_numbers = [2, 4, 6, 8, 10] powers = [1, 2, 3, 4, 5]

Мы передадим функцию pow() в качестве аргумента в map () и предоставим два списка в качестве наших итерируемых объектов:

numbers_powers = list(map(pow, base_numbers, powers))

Функция map() применит pow() к каждому элементу в каждом списке, чтобы возвести число в указанную степень. Поэтому в результате мы получим 2**1, 4**2, 6**3 и так далее:

[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)

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

[2, 16, 216, 4096, 100000]

Итак, мы использовали функцию map() со встроенной функцией Python и увидели, что она может обрабатывать несколько итерируемых объектов одновременно. Кроме того, теперь вы знаете, что map() обрабатывает несколько итерируемых объектов, пока не достигнет конца объекта с наименьшим количеством элементов.

Заключение

Здесь мы рассмотрели несколько различных способов использования функции map() в Python. Чтобы потренироваться, вы можете попробовать использовать map() со своей собственной пользовательской функцией, лямбда-функцией и с любыми встроенными функциями, даже если они требуют нескольких итерируемых объектов.

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

Читайте также: Как работает функция filter() в Python 3

Tags: ,

Добавить комментарий