Historia pytania
Funkcja map() pochodzi z programowania funkcyjnego (jeszcze z Lispa), jej zadaniem jest stosowanie funkcji do każdego elementu sekwencji, zwracając nowy obiekt iterowalny z wynikami. W Pythonie powstała na długo przed pojawieniem się wyrażeń generatorowych i wyrażeń listowych, ale wciąż jest szeroko stosowana, szczególnie w dużych pipelines przetwarzania danych.
Problem
Jeśli konieczne jest przekształcenie każdego elementu kolekcji według jakiejś zasady, rozwiązania typu for-pętli szybko stają się nieczytelne. Wyrażenia listowe i map() pozwalają wyrazić zamiar w bardziej zwięzły sposób. Ważne jest, aby zrozumieć różnice między tymi podejściami, aby prawidłowo wybrać narzędzie.
Rozwiązanie
map(func, iterable) tworzy leniwego iteratora, w którym elementy oryginalnej sekwencji są przekształcane przez funkcję funcmap nie oblicza elementów od razu, a działa leniwiedef square(x): return x * x squares = map(square, [1, 2, 3]) print(list(squares)) # [1, 4, 9]
Wyrażenie listowe [square(x) for x in [1, 2, 3]] robi to samo, ale od razu zwraca listę, a wyrażenie generatorowe (square(x) for x in [1, 2, 3]) to leniwy generator.
Kluczowe cechy:
Czy map() zwraca listę w Pythonie 3?
Nie, od momentu wprowadzenia Pythona 3, map() zwraca nie listę, a leniwego iteratora. Aby uzyskać listę — trzeba ręcznie owijać wynik w list().
res = map(str.upper, ['a', 'b']) print(res) # <map object ...> print(list(res)) # ['A', 'B']
Czy można za pomocą map() dodać warunek filtrowania wewnątrz funkcji?
Nie, map() nie filtruje elementów, a jedynie przekształca. Do filtrowania używaj filter() lub wyrażenia listowego:
result = map(str.upper, ['a', 'b', None]) # Jeśli przyjdzie None, map wywoła błąd wywołania str.upper(None) # filter pomoże usunąć None przed map
Czy można za pomocą map() jednocześnie iterować po dwóch sekwencjach?
Tak, map() potrafi przyjmować dowolną liczbę sekwencji, a funkcja-przekształcająca musi przyjmować tyle samo argumentów:
x = [1, 2, 3] y = [10, 20, 30] result = map(lambda a, b: a + b, x, y) print(list(result)) # [11, 22, 33]
Programista oczekuje, że otrzyma listę od razu:
mapped = map(abs, [-1, -2, -3]) print(mapped[1]) # TypeError: 'map' object is not subscriptable
Zalety:
Wady:
Użycie wyrażenia generatorowego do filtrowania i map() do przekształcania:
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]
Zalety:
Wady: