Функция map() в функциональном программировании 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 для таких случаев.