Функция map() в функциональном программировании Python

Раздел: Python -> Функциональное программирование

Работа функции map() со списками в Python

Основное решение: преобразование списка строк в числа

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

Как превратить список строковых чисел в список целых чисел без цикла?


# Исходный список строк
str_nums = ["10", "20", "30", "40"]

# Применяем map с функцией int
result = list(map(int, str_nums))

print(result)  # [10, 20, 30, 40]
  

List map python (функция map со списком в python)

Типичная ошибка: забыть преобразовать map-объект в список. Без list() результат не будет списком и его нельзя проиндексировать. Решение - всегда использовать list(), если нужен список.

Этот подход эффективен, потому что map ленив (выполняется только при обходе) и использует встроенную функцию без дополнительных затрат.

Как применить собственное преобразование (например, возвести в квадрат)?

Используйте лямбда-функцию.


nums = [1, 2, 3, 4, 5]

squared = list(map(lambda x: x ** 2, nums))
print(squared)  # [1, 4, 9, 16, 25]
  

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

Цель: быстрое однострочное преобразование, когда функция не нужна повторно.

Как обработать несколько списков поэлементно (например, сложить)?

map принимает несколько итераторов. Функция должна принимать столько аргументов, сколько передано списков.


a = [1, 2, 3]
b = [4, 5, 6]

sum_ab = list(map(lambda x, y: x + y, a, b))
print(sum_ab)  # [5, 7, 9]
  

Ошибка: списки разной длины. map останавливается на самом коротком. Если нужно дополнить, используйте zip_longest из itertools.

Случаи использования: поэлементное сложение, конкатенация, сравнение.

Как применить метод строки (например, strip) ко всем элементам?

Передайте имя метода без вызова: метод сам будет применён через map.


words = ["  привет  ", "мир ", "  Python"]
cleaned = list(map(str.strip, words))
print(cleaned)  # ['привет', 'мир', 'Python']
  

Распространённая ошибка: написать map(str.strip(), words) – это вызывает метод без аргументов один раз, а не применяет его к каждому элементу. Всегда передавайте ссылку на функцию или метод.

Цель: чистая и короткая обработка строк без написания собственной функции.

Почему map не возвращает список сразу и как использовать ленивость?

map() возвращает итератор, который вычисляет значения по мере запроса. Это экономит память при работе с большими данными.


m = map(int, ["1", "2", "3"])
print(type(m))  # 
# Для получения следующих элементов используйте next()
print(next(m))  # 1
print(next(m))  # 2
  

Проблема: итератор можно обойти только один раз. После использования его нужно создать снова. Если не вызвать list() и попытаться использовать результат как обычный список, возникнут ошибки (например, не работает len). Решение: если нужен многоразовый доступ, сохраняйте список.

Ленивый подход полезен для цепочек преобразований (map, filter) без материализации промежуточных списков.

Как применить функцию, возвращающую кортеж, и распаковать результаты?

Совместите map и zip


def divmod_pair(x):
    return divmod(x, 3)

pairs = list(map(divmod_pair, range(5)))
# [(0,0), (0,1), (0,2), (1,0), (1,1)]
quotients, remainders = zip(*pairs)
print(list(quotients))   # [0, 0, 0, 1, 1]
print(list(remainders))  # [0, 1, 2, 0, 1]
  

Ошибка: забыть распаковать с помощью * или перепутать порядок. Убедитесь, что длина кортежей одинакова.

Этот приём удобен при параллельной обработке нескольких атрибутов.

Расширенные примеры использования map()

1. Комбинирование map и filter для проверки условий

Хотя map не фильтрует, можно сначала применить filter, затем map.

Пример

# Получить квадраты чисел, которые делятся на 3
numbers = range(15)
filtered = filter(lambda x: x % 3 == 0, numbers)
squares = list(map(lambda x: x ** 2, filtered))
print(squares)  # [0, 9, 36, 81, 144]
[0, 9, 36, 81, 144]

Пояснение: filter оставляет только нужные элементы, после чего map преобразует их без создания промежуточного списка.

2. Использование map с functools.partial

Когда нужно передать функцию с фиксированными аргументами.

Пример

from functools import partial

def multiply(x, factor):
    return x * factor

double = partial(multiply, factor=2)
nums = [1, 2, 3, 4]
doubled_nums = list(map(double, nums))
print(doubled_nums)  # [2, 4, 6, 8]
[2, 4, 6, 8]

Проблемы: partial может запутать при неправильном указании аргументов. Решение - явно указывать имена параметров.

3. Создание экземпляров классов через map

Пример

class Person:
    def __init__(self, name):
        self.name = name
    def __repr__(self):
        return f'Person({self.name!r})'

names = ["Анна", "Борис", "Виктор"]
persons = list(map(Person, names))
print(persons)  # [Person('Анна'), Person('Борис'), Person('Виктор')]
[Person('Анна'), Person('Борис'), Person('Виктор')]

Внимание: конструктор вызывается с одним аргументом, поэтому для нескольких параметров нужна дополнительная обработка (например, через лямбду).

4. Извлечение значений из списка словарей

Пример

users = [
    {'name': 'Alice', 'age': 25},
    {'name': 'Bob', 'age': 30},
    {'name': 'Charlie', 'age': 35}
]

ages = list(map(lambda user: user['age'], users))
print(ages)  # [25, 30, 35]
[25, 30, 35]

Для отсутствующего ключа возникнет KeyError. Используйте dict.get для безопасного доступа.

5. Сравнение производительности map и list comprehension

Пример

import timeit

# Подготовка
nums = list(range(10**6))

# map + lambda
map_time = timeit.timeit(
    'list(map(lambda x: x*x, nums))',
    globals=globals(),
    number=10
)

# list comprehension
comp_time = timeit.timeit(
    '[x*x for x in nums]',
    globals=globals(),
    number=10
)

print(f'map: {map_time:.4f} с')
print(f'list comp: {comp_time:.4f} с')
Примерный вывод (зависит от системы):
map: 0.5123 с
list comp: 0.4876 с

Разница незначительна, но list comprehension часто читаемее. map может быть быстрее при использовании встроенной функции (например, int) вместо лямбды.

6. Распаковка аргументов с itertools.starmap

Пример

from itertools import starmap

pairs = [(1, 2), (3, 4), (5, 6)]
# Эквивалент map с lambda, но starmap распаковывает кортежи
result = list(starmap(lambda a, b: a * b, pairs))
print(result)  # [2, 12, 30]
[2, 12, 30]

Удобно, когда данные уже представлены как последовательность кортежей.

7. Ошибка: функция с побочными эффектами в map

Пример

# Не рекомендуется: map не гарантирует порядок выполнения (но на практике последовательный)
nums = [1, 2, 3]
output = []
def append_and_return(x):
    output.append(x * 2)
    return x * 2

result = list(map(append_and_return, nums))
print('output list:', output)  # [2, 4, 6]
print('map result:', result)   # [2, 4, 6]
output list: [2, 4, 6]
map result: [2, 4, 6]

Проблема: если функция изменяет внешнее состояние, код становится трудным для отладки. Лучше использовать явный цикл for для таких случаев.

Функция map со списком в Python - comments

En
List map python (python)