История вопроса
Функция map() пришла из функционального программирования (еще из Lisp), её назначение — применять функцию к каждому элементу последовательности с возвратом нового итерируемого объекта с результатами. В Python она возникла задолго до появления генераторных и списковых выражений, но до сих пор широко используется, особенно в больших пайплайнах обработки данных.
Проблема
Если требуется изменить каждый элемент коллекции по какому-то правилу, решения вида for-циклов быстро становятся громоздкими и менее читаемыми. Списковые выражения и map() позволяют выразить намерение компактно. При этом важно понимать различия этих подходов, чтобы правильно выбрать инструмент.
Решение
map(func, iterable) создаёт ленивый итератор, в котором элементы исходной последовательности преобразованы функцией funcmap не вычисляет элементы сразу, а работает ленивоdef square(x): return x * x squares = map(square, [1, 2, 3]) print(list(squares)) # [1, 4, 9]
Списковое выражение [square(x) for x in [1, 2, 3]] делает то же, но сразу возвращает список, а генераторное выражение (square(x) for x in [1, 2, 3]) — это ленивый генератор.
Ключевые особенности:
Возвращает ли map() список в Python 3?
Нет, начиная с Python 3, map() возвращает не список, а ленивый итератор. Чтобы получить список — нужно вручную обернуть результат в list().
res = map(str.upper, ['a', 'b']) print(res) # <map object ...> print(list(res)) # ['A', 'B']
Можно ли с помощью map() добавить условие фильтрации внутри функции?
Нет, map() не фильтрует элементы, а только преобразует. Для фильтрации используйте filter() или списковое выражение:
result = map(str.upper, ['a', 'b', None]) # Если прилетит None, map вызовет ошибку вызова str.upper(None) # filter поможет убрать None до map
Можно ли с помощью map() одновременно перебрать две последовательности?
Да, map() умеет принимать произвольное количество последовательностей, а функция-преобразователь обязана принимать столько же аргументов:
x = [1, 2, 3] y = [10, 20, 30] result = map(lambda a, b: a + b, x, y) print(list(result)) # [11, 22, 33]
Разработчик ожидает получить список сразу:
mapped = map(abs, [-1, -2, -3]) print(mapped[1]) # TypeError: 'map' object is not subscriptable
Плюсы:
Минусы:
Использование генераторного выражения для фильтрации и map() для преобразования:
nums = range(-5, 6) positives = (x for x in nums if x > 0) sq = map(lambda n: n * n, positives) print(list(sq)) # [1, 4, 9, 16, 25, 36]
Плюсы:
Минусы: