fbpx

Mateusz Mazurek – programista z pasją

Czyli o użyciu Pythona i kilku innych technologii do tworzenia świetnej jakości aplikacji w oparciu o stabilny proces dostarczania oprogramowania.

Programowanie Programowanie webowe

For vs list comprehension vs map

Cześć,

dziś wezmę na tapet trzy elementy języka Python:

  • pętlę for,
  • list comprehension,
  • funkcję map.

Pomierzymy sobie ich efektywność w dwóch sytuacjach i na koniec wyciągniemy wnioski, odpowiadając na pytanie: co jest szybsze: pętla for, list comprehension czy funkcja map? Zapraszam!

Sytuacja pierwsza: wynik jest nam potrzebny

Wyobraźmy sobie, że działamy pętlą po jakiejś kolekcji, na jej elementach wykonujemy funkcję i wynik tej funkcji potrzebujemy zachować. Może to być np. wygenerowanie potęg liczb od 0 do 99. Możemy to zrobić na trzy sposoby:

Za pomocą standardowej pętli for:

1
2
3
numbers = []
for x in range(100):
    numbers.append(x * x)

Następnie z użyciem starej, dobrej listy składanej:

1
numbers = [x * x for x in range(100)]

I na koniec – funkcji map:

1
numbers = list(map(lambda x: x * x, range(100)))

Aby była pewność, że każde z tych podejść da ten sam efekt, dorzucam kawałek kodu, który to potwierdza:

1
2
3
4
5
6
7
8
9
numbers = []
for x in range(100):
    numbers.append(x * x)
   
numbers2 = [x * x for x in range(100)]

numbers3 = list(map(lambda x: x * x, range(100)))

print(numbers == numbers2 == numbers3)

Jego rezultatem jest oczywiście „True”.

Jeżeli ten sam rezultat można uzyskać na trzy różne sposoby, to który wybrać? Zmierzmy to!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from timeit import timeit

code1 = """
numbers = []
for x in range(100):
    numbers.append(x * x)
"""


code2 = """
numbers = [x * x for x in range(100)]
"""


code3 = """
numbers = list(map(lambda x: x * x, range(100)))
"""



print("For loop:", timeit(code1, number=100000))
print("List comp:", timeit(code2, number=100000))
print("Funkcja map:", timeit(code3, number=100000))

Wynik pomiaru jest dość ciekawy:

For loop: 1.0205242090160027
List comp: 0.6673786389874294
Funkcja map: 1.0319141389336437

Tę kategorię wygrywa, przeciwników zostawiając w tyle, podejście z użyciem list comprehensions!


Czekaj, stop!

Podoba Ci się to co tworzę? Jeśli tak to zapraszam Cię do zapisania się na newsletter:
a w ramach prezentu otrzymasz całkowicie za darmo, dokument PDF „6 (nie zawsze oczywistych) błędów popełnianych podczas nauki programowania” który jest jednym z efektów ponad siedmioletniej pracy oraz obserwacji rozwoju niejednego programisty.Jeśli to Cię interesuje to zapraszam również na swoje social media.

Sytuacja druga: wynik nie jest nam potrzebny

Nasze podejście trochę się zmienia, gdy zmienia się sytuacja w której używamy tych elementów. W poprzednim przykładzie wynik przetwarzania miał być nam potrzebny w dalszej części programu. Teraz zakładamy, że nie jest on mam potrzebny. Mamy znów trzy podejścia. Kolejno z pętlą for, listą składaną oraz funkcją map:

1
2
for x in numbers:
    mock(x)
1
[mock(x) for x in numbers]
1
list(map(mock, numbers))

Tutaj słowo wyjaśnienia – funkcja map tworzy generator i nie uruchomi naszej funkcji, dopóki nie będzie ku temu okazji. Okazję wymuszamy konwersją na listę.

Skoro mamy zebrane rzeczy do analizy, to tak jak wcześniej, zmierzmy to!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from timeit import timeit


setup = """
def mock(x):
    return x * x

numbers = range(100)
"""


code1 = """
for x in numbers:
    mock(x)
"""


code2 = """
[mock(x) for x in numbers]
"""


code3 = """
list(map(mock, numbers))
"""


print("For loop:", timeit(code1, number=100000, setup=setup))
print("List comp:", timeit(code2, number=100000, setup=setup))
print("Funkcja map:",timeit(code3, number=100000, setup=setup))

Rezultaty pomiaru:

For loop: 0.9080528659978881
List comp: 1.028726649004966
Funkcja map: 0.8416485550114885

Tutaj nie ma już jednogłośnego zwycięzcy. Niby funkcja map wygrywa, ale jest tylko troszkę szybsza niż pętla for.

Podsumownie

Wnioski nasuwają się same, prawda? Jeśli potrzebujesz pracować na danych w dalszej części programu, to używaj listy składanej. Jeśli nie ma potrzeby pracy na wyniku przetwarzania, a samo uruchomienie funkcji jest wystarczające to… To tu nie jest tak jednoznacznie. To, co bym polecał, to jednak używać pętli for. Różnica jest niewielka, a czytelność znacznie lepsza.

Oczywiście nie wszystkie pętle jesteśmy w stanie zapisać z użyciem list składanych czy zapakować do funkcji map. Przykładowo, jeśli Twoja pętla posiada słówka break lub continue, to może być ciężko.

Dzięki za wizytę,
Mateusz Mazurek

A może wolisz nowości na mail?

4
Dodaj komentarz

avatar
2 Wątki
2 Odpowiedzi
2 Śledzący
 
Komentarz z największą liczbą reakcji
Najczęściej komentowany wątek
3 Komentarze autora
Mateusz M.ŁukaszKrzysztof Ostatnie komentarze autora

Witryna wykorzystuje Akismet, aby ograniczyć spam. Dowiedz się więcej jak przetwarzane są dane komentarzy.

  Subskrybuj  
Powiadom o
Krzysztof
Gość

super wytłumaczone, robisz świetną robotę, dziękuję

Łukasz
Gość

Ja najczęściej korzystam z .map :)

Halo, halo, czekaj chwilę, nie zamykaj!

Super się cieszę że tu jesteś! Bloga tego prowadzę już jakiś czas, uwielbiam pisać i dzielić się wiedzą ale moja pasja do tego jest bez sensu jeśli nie mam czytelników :(

W tej chwili chciałbym Cię zaprosić do zapisania się na newsletter i bycia na bieżąco z tym co przygotowuję. W zamiana za okazane zaufanie dostaniesz dostęp do dokumentu PDF

6(nie zawsze oczywistych) błędów popełnianych podczas nauki programowania”

całkowicie ZA DARMO – wiem, szok i niedowierzanie że daje coś za darmo. Ale ja serio lubię się dzielić wiedzą! Zostaw po prostu swój mail tu – link do zapisania się.