map() в Python: применение функции к каждому элементу
Как работает map в Python: map(func, iterable), несколько списков, ленивость и list(), map(int, input().split()), lambda, map или list comprehension, filter.
Содержание · 11 разделов
- Синтаксис map
- map со встроенными функциями и методами
- map(int, input().split()): ввод чисел в одну строку
- Несколько итерируемых объектов
- Ленивость: почему map нужно превращать в list
- map и словари
- map или списковое включение: что выбрать
- filter: отбор элементов
- Частые ошибки
- Вывод <map object at 0x...> вместо значений
- Скобки после имени функции
- Число аргументов не совпадает с числом списков
- Повторное использование объекта map
- len() и индексация
- Ошибка появляется «не там»
- Частые вопросы
- Как передать функции в map дополнительный аргумент?
- Как прочитать числа, записанные через запятую?
- Как прочитать числа, если каждое стоит на отдельной строке?
- Это то же самое, что map в C++ или Java?
- Итог
map() в Python — встроенная функция, которая применяет другую функцию к каждому элементу итерируемого объекта и возвращает результаты по одному. Самый частый пример — превратить строки в числа:
numbers = ["1", "2", "3"]
result = map(int, numbers)
print(list(result)) # → [1, 2, 3]
Главное, что нужно запомнить: map возвращает не список, а ленивый объект map, поэтому для вывода и повторного использования его оборачивают в list(). Ниже — синтаксис, работа с несколькими списками, разбор map(int, input().split()), сравнение со списковым включением и типичные ошибки. Примеры проверены на Python 3.12.
Синтаксис map
map(function, iterable, *iterables)
map(function, iterable, *iterables, strict=False) # Python 3.14+
function— функция, которую нужно применить. Передаётся сама функция, без скобок:int, а неint().iterable— список, кортеж, строка, словарь, файл или другой итерируемый объект.*iterables— дополнительные последовательности, если функция принимает несколько аргументов.strict— только именованный, появился в Python 3.14: приstrict=Trueпоследовательности разной длины вызываютValueError.
Функцией может быть встроенная функция, ваша собственная функция, метод класса или lambda:
def square(x):
return x * x
print(list(map(square, [1, 2, 3, 4]))) # → [1, 4, 9, 16]
print(list(map(lambda x: x * x, [1, 2, 3, 4]))) # → [1, 4, 9, 16]
Оба варианта дают одно и то же. Своя функция с именем удобнее, если логика длиннее одного выражения или используется в нескольких местах.
map со встроенными функциями и методами
Сильнее всего map выглядит, когда функция уже существует и не нужна lambda:
words = ["python", "django", "fastapi"]
print(list(map(str.upper, words))) # → ['PYTHON', 'DJANGO', 'FASTAPI']
print(list(map(len, words))) # → [6, 6, 7]
print(list(map(str, [1, 2, 3]))) # → ['1', '2', '3']
print(list(map(float, ["3.14", "2"]))) # → [3.14, 2.0]
print(list(map(abs, [-3, 0, 2]))) # → [3, 0, 2]
print(list(map(str.strip, [" a ", "b ", " c"]))) # → ['a', 'b', 'c']
В str.upper и str.strip метод вызывается через класс, а каждый элемент подставляется как self. Так можно использовать любой метод без аргументов.
Классический приём — склеить числа в строку. Метод join принимает только строки, поэтому числа сначала проходят через map(str, ...):
print(" ".join(map(str, [1, 2, 3]))) # → 1 2 3
Подробнее о склейке строк — в статье про метод join().
map(int, input().split()): ввод чисел в одну строку
Эту конструкцию встречает каждый, кто решает олимпиадные или учебные задачи. Разберём её по шагам на вводе 3 5:
input()читает строку:"3 5"..split()делит её по пробелам:["3", "5"].map(int, ...)применяетintк каждой части и выдаёт3и5.- Результат распаковывается в переменные или собирается в список.
a, b = map(int, input().split())
print(a + b)
# ввод: 3 5
# вывод: 8
numbers = list(map(int, input().split()))
print(numbers, sum(numbers))
# ввод: 10 20 30 40
# вывод: [10, 20, 30, 40] 100
Распаковка a, b = ... работает и без list(): Python сам переберёт объект map. Но количество чисел во вводе должно совпадать с числом переменных — при вводе 1 2 3 будет ValueError: too many values to unpack (expected 2).
Без .split() map пройдёт по строке посимвольно, и int упадёт на пробеле:
list(map(int, "12 5")) # ValueError: invalid literal for int() with base 10: ' '
list(map(int, "12 5".split())) # → [12, 5]
Как устроен split() и его аргументы — в статье про split() в Python.
Несколько итерируемых объектов
Если передать несколько последовательностей, функция получит по одному элементу из каждой — так же, как в zip(). Число аргументов функции должно совпадать с числом последовательностей:
a = [1, 2, 3]
b = [10, 20, 30]
print(list(map(lambda x, y: x + y, a, b))) # → [11, 22, 33]
print(list(map(pow, [2, 3, 4], [3, 2, 1]))) # → [8, 9, 4] 2**3, 3**2, 4**1
print(list(map(max, [1, 5, 3], [4, 2, 6]))) # → [4, 5, 6]
Вместо lambda x, y: x + y можно взять готовую функцию из модуля operator: map(operator.add, a, b).
Важно:
mapостанавливается на самой короткой последовательности. Лишние элементы молча отбрасываются, ошибки не будет:
print(list(map(lambda x, y: x * y, [1, 2, 3], [10, 20]))) # → [10, 40]
В Python 3.14 у map появился параметр strict, как у zip() с версии 3.10. С strict=True разная длина последовательностей вызывает ошибку, и потерянные данные не останутся незамеченными:
# Python 3.14+
list(map(lambda x, y: x * y, [1, 2, 3], [10, 20], strict=True))
# ValueError: map() argument 2 is shorter than argument 1
В версиях до 3.14 параметра нет, и такой вызов завершится TypeError (в Python 3.12 — map() takes no keyword arguments).
Если данные уже лежат парами — списком кортежей, — используйте itertools.starmap, он распаковывает каждый кортеж в аргументы:
from itertools import starmap
print(list(starmap(pow, [(2, 3), (3, 2)]))) # → [8, 9]
Ленивость: почему map нужно превращать в list
map ничего не вычисляет в момент вызова. Он возвращает итератор, который вызывает функцию только тогда, когда у него просят следующий элемент:
def noisy(x):
print("обрабатываю", x)
return x * 10
m = map(noisy, [1, 2, 3])
print("map создан")
print(next(m))
print(list(m))
print(list(m))
map создан
обрабатываю 1
10
обрабатываю 2
обрабатываю 3
[20, 30]
[]
Из этого примера видно три свойства:
- Вычисление откладывается. Пока вы не начали перебор, функция не вызвана ни разу. Поэтому ошибка в данных проявится не на строке с
map, а позже — там, где результат используется. - Объект одноразовый. После полного прохода итератор пуст, второй
list(m)вернёт[]. - Экономия памяти. Промежуточный список не создаётся, что важно для больших файлов и длинных последовательностей.
Если результат нужен целиком или несколько раз — сохраните его: list(map(...)), tuple(map(...)) или set(map(...)). Если он сразу передаётся в функцию, которая сама перебирает элементы, list() не нужен:
print(sum(map(int, ["10", "20", "30"]))) # → 60
print(max(map(len, words))) # → 7
for n in map(int, ["7", "8"]):
print(n)
# → 7
# → 8
map и словари
При переборе словаря map получает ключи. Для значений передайте d.values(), для пар — d.items():
prices = {"кофе": 150, "чай": 90}
print(list(map(str.upper, prices))) # → ['КОФЕ', 'ЧАЙ']
print(list(map(lambda kv: f"{kv[0]}: {kv[1]} ₽", prices.items())))
# → ['кофе: 150 ₽', 'чай: 90 ₽']
Чтобы получить новый словарь, генератор словаря обычно читается лучше, чем комбинация dict, zip и map: {name: price * 2 for name, price in prices.items()}. Подробнее — в статье про словари в Python.
map или списковое включение: что выбрать
Почти любой map можно переписать как списковое включение (list comprehension):
list(map(int, numbers)) # → [1, 2, 3]
[int(s) for s in numbers] # → [1, 2, 3]
list(map(lambda x: x * x, [1, 2, 3, 4])) # → [1, 4, 9, 16]
[x * x for x in [1, 2, 3, 4]] # → [1, 4, 9, 16]
| Ситуация | Лучше |
|---|---|
Готовая функция: int, str, len, str.strip | map(int, items) — коротко и ясно |
Нужно выражение — пришлось бы писать lambda | включение [x * 2 for x in items] |
| Нужна фильтрация по условию | включение с if |
| Результат перебирается один раз, список не нужен | map или генераторное выражение (… for …) |
| Нужен словарь или множество | генератор словаря или множества |
По скорости разница невелика и не должна быть главным аргументом. Пример одного замера timeit на Python 3.12 и списке из 10 000 элементов: list(map(int, s)) — около 1,1 мс, [int(x) for x in s] — около 1,5 мс; map с lambda x: x * 2 — около 1 мс против 0,4 мс у включения [x * 2 for x in n]. Для lambda на каждый элемент вызывается дополнительная Python-функция, поэтому такой map обычно проигрывает. Повторите замер на своих данных и версии Python, прежде чем делать выводы.
Практическое правило: есть готовая функция — map, нужно писать lambda — включение.
filter: отбор элементов
filter(function, iterable) — родственник map. Он не преобразует элементы, а оставляет те, для которых функция вернула истинное значение. Результат тоже ленивый:
nums = [1, 2, 3, 4, 5, 6]
print(list(filter(lambda n: n % 2 == 0, nums))) # → [2, 4, 6]
Если вместо функции передать None, filter уберёт все «ложные» значения — 0, пустые строки и списки, None:
print(list(filter(None, [0, 1, "", "a", None, [], [2]]))) # → [1, 'a', [2]]
map и filter можно комбинировать, но включение с условием обычно читается проще:
print(list(map(lambda n: n * n, filter(lambda n: n % 2 == 0, nums)))) # → [4, 16, 36]
print([n * n for n in nums if n % 2 == 0]) # → [4, 16, 36]
Частые ошибки
Вывод <map object at 0x...> вместо значений
print(map(int, ["1", "2", "3"])) # → <map object at 0x000002A51891AE30>
Так Python показывает сам объект-итератор: значения появятся только при обходе. Оберните результат в list().
Скобки после имени функции
list(map(int(), ["1"])) # TypeError: 'int' object is not callable
int() вызывает функцию и возвращает 0, а map нужна сама функция. Сам вызов map(int(), ...) ошибки не даёт — она появится при переборе результата. Пишите map(int, ...).
Число аргументов не совпадает с числом списков
a = [1, 2]
b = [3, 4]
list(map(lambda x: x * 2, a, b))
# TypeError: <lambda>() takes 1 positional argument but 2 were given
Два списка — значит, функция должна принимать два аргумента.
Повторное использование объекта map
После list(m) или цикла for объект пуст. Если результат нужен дважды, сохраните список: values = list(map(...)).
len() и индексация
len(map(int, ["1"])) # TypeError: object of type 'map' has no len()
map(int, ["1"])[0] # TypeError: 'map' object is not subscriptable
Объект map — итератор, а не последовательность. Сначала превратите его в список.
Ошибка появляется «не там»
m = map(int, ["1", "x"]) # ошибки нет
list(m) # ValueError: invalid literal for int() with base 10: 'x'
Из-за ленивости traceback указывает на строку, где результат перебирается. Ищите плохие данные во входной последовательности. Как разбирать такие сообщения, рассказано в статье про traceback и ошибки Python.
Частые вопросы
Как передать функции в map дополнительный аргумент?
Зафиксируйте его через lambda или functools.partial. Второй вариант не создаёт новую функцию вручную и удобен для встроенных функций с именованными параметрами.
from functools import partial
prices = [1.2345, 9.876, 3.14159]
print(list(map(lambda x: round(x, 2), prices))) # → [1.23, 9.88, 3.14]
print(list(map(partial(round, ndigits=2), prices))) # → [1.23, 9.88, 3.14]
Как прочитать числа, записанные через запятую?
Передайте разделитель в split(","). Пробелы вокруг чисел убирать не нужно: int() сам отбрасывает пробельные символы по краям строки.
print(list(map(int, "10, 20,30".split(",")))) # → [10, 20, 30]
Как прочитать числа, если каждое стоит на отдельной строке?
Если количество строк известно, вызывайте input() в генераторе списка: [int(input()) for _ in range(n)]. Если нет, прочитайте весь ввод сразу: list(map(int, sys.stdin.read().split())) — split() без аргументов делит и по переводам строки.
Это то же самое, что map в C++ или Java?
Нет. В C++ и Java map — структура «ключ — значение», в Python ей соответствует словарь dict. Встроенная функция map() в Python ничего не хранит: она применяет функцию к элементам последовательности.
Итог
map(func, iterable) применяет функцию к каждому элементу и возвращает ленивый итератор: оборачивайте его в list(), когда нужен готовый список. Используйте map с готовыми функциями — int, str, len, методами строк, — а для выражений и фильтрации выбирайте списковое включение. Если вместе с элементом нужен его номер, пригодится функция enumerate(). Остальные встроенные функции и конструкции языка собраны в шпаргалке по синтаксису Python, а потренироваться с map(int, input().split()) можно на задачах по Python с решениями.
- #Python
- #map
- #lambda
- #filter
- #Встроенные функции