map() vs list comprehension
map() wywołuje funkcję dla każdego elementu i zwraca leniwy iterator, a wyrażenie listowe buduje nową listę od razu i umie filtrować elementy warunkiem if.
Porównanie w tabeli
#Co zwraca
- map()
- Iterator (leniwy)
- Wyrażenia listowe
- Listę (od razu, w pamięci)
Wymaga funkcji
- map()
- Tak, istniejącej funkcji albo lambdy
- Wyrażenia listowe
- Nie, wyrażenie piszesz wprost
Filtrowanie elementów
- map()
- Potrzebny osobny
filter() - Wyrażenia listowe
- Wbudowane
ifna końcu
Można przejść wynik tylko raz
- map()
- Tak
- Wyrażenia listowe
- Nie, to zwykła lista
Czytelność przy prostych przekształceniach
- map()
- Niższa, potrzebna dodatkowa funkcja lub lambda
- Wyrażenia listowe
- Wyższa, jedna linia
Typowe użycie
- map()
- Gotowa funkcja, leniwe przetwarzanie
- Wyrażenia listowe
- Krótkie przekształcenia, przekształcenia z warunkiem
Przykład
#values = ["12", "7", "30"]
doubled_map = list(map(lambda v: int(v) * 2, values))
doubled_comprehension = [int(v) * 2 for v in values]
print(doubled_map)
print(doubled_comprehension)
print(doubled_map == doubled_comprehension)Definicja i zastosowanie
#Obie przekształcają kolekcję element po elemencie, dając nowy ciąg wartości tej samej długości, o ile nie filtrujesz. W obu przypadkach oryginalna kolekcja się nie zmienia.
Różnią się składnią i tym, kiedy powstają wyniki. map(funkcja, kolekcja) potrzebuje już istniejącej funkcji albo lambdy i zwraca iterator: wartości powstają leniwie, dopiero gdy o nie poprosisz, np. w list() albo pętli for, i da się po nim przejść tylko raz. Wyrażenie listowe ([wyrazenie for x in kolekcja]) od razu tworzy całą listę w pamięci, a opcjonalny warunek if na końcu filtruje elementy bez dodatkowego wywołania filter().
Gdy masz już nazwaną funkcję i potrzebujesz leniwego iteratora, np. do dalszego łączenia z innymi iteratorami, map() bywa wygodny. W większości kodu czytelniejsze jest wyrażenie listowe, zwłaszcza gdy przekształcenie jest krótkie albo trzeba dodać warunek. Wersja z nawiasami okrągłymi, czyli wyrażenie generatorowe, daje taką samą leniwość jak map().
Składnia
#map(funkcja, iterable)
[wyrazenie for element in iterable if warunek]Więcej przykładów
#numbers = [1, 2, 3]
result = map(lambda n: n * n, numbers)
print(type(result).__name__)
print(list(result))
print(list(result))Iterator zużywa się po pierwszym przejściu. Druga próba zamiany na listę daje już pustą listę.
scores = [45, 82, 67, 91, 30]
passed_comprehension = [s for s in scores if s >= 60]
passed_map_filter = list(filter(lambda s: s >= 60, map(lambda s: s, scores)))
print(passed_comprehension)
print(passed_comprehension == passed_map_filter)Dobre praktyki
#- Potrzebujesz tylko przekształcenia bez warunku? Obie opcje działają, ale wyrażenie listowe zwykle łatwiej czyta się w Pythonie.
- Gdy trzeba przefiltrować i przekształcić naraz, wyrażenie listowe z
ifjest krótsze niż łączeniemap()ifilter(). - Jeśli dane są bardzo duże i chcesz przetwarzać je leniwie bez tworzenia listy, użyj
map()albo wyrażenia generatorowego(wyrazenie for x in kolekcja).
Powiązane hasła
#Widzisz błąd albo brakuje przykładu? Napisz do nas.