BiteSize - iterables unpacking rozpakowywanie danych
BiteSize, Technicznie

Python iterables unpacking (BiteSize) – rozpakowywanie danych

Cześć, w tym wpisie z kategorii BiteSize zajmiemy się rozpakowywaniem zmiennych iterowalnych (ang. iterables unpacking) i zobaczysz, po co i dlaczego warto je stosować. Poprawimy czytelność kodu i będziemy mogli się pozbyć wielu magicznych liczb (ang. magic numbers).

Problem do rozwiązania

Mamy listę krotek (list of tuples) rankingu konkursu. Każda krotka składa się z imienia i ilości zdobytych punktów. Następnie chcemy podać zwycięzców (3 miejsca z podium) i sprawdzić, jaki był najgorszy wynik. Przykładowe dane przedstawiam poniżej. Zakładam, że lista jest posortowana po ilości punków.

ranking = [
    ("Michał", 139),
    ("Zosia", 123),
    ("Kasia", 112),
    ("Grzesiek", 99),
    ("Łukasz", 85),
    ...,
    ("Wojtek", 34),
]

Przykładowe rozwiązanie

Wiedząc, że tak jak wszyscy programiści liczymy od zera, a indeks -1 oznacza ostatni element, można łatwo napisać taki kod.

first = ranking[0]
second = ranking[1]
third = ranking[2]
others = ranking[3:-1]
last = ranking[-1]

# Same thing in one line
first, second, third, others, last = ranking[0], ranking[1], ranking[2], ranking[3:-1], ranking[-1] 

print(f"First place for {first[0]} with {first[1]} points.")
print(f"Second place for {second[0]} with {second[1]} points.")
print(f"Third place for {third[0]} with {third[1]} points.")
print(f"Smallest number of points gotten is {last[1]}.")

Jest to całkiem okej i nie ma co się tutaj zbytnio kłócić. Jednak jak to często powtarza jeden z core developerów języka Python:

There must be a better way!

Raymond Hettinger

Jestem zwolennikiem podejścia – „Najpierw ma działać” oraz czasami „Jak działa, to nie ruszaj„. Co nie znaczy, że nie można bardziej Pythonowo.

Iterables unpacking

Jedno z pytań, które się nasuwa to, czym są iterables? Na potrzeby tego wpisu, powiem tylko, że to zmienne, po których możemy iterować. Zresztą jak na to sama nazwa wskazuje.

Wykorzystując rozpakowywanie, możemy zapisać to w następujący sposób.

first, second, third, *others, last = ranking

print(f"First place for {first[0]} with {first[1]} points.")
print(f"Second place for {second[0]} with {second[1]} points.")
print(f"Third place for {third[0]} with {third[1]} points.")
print(f"Smallest number of points gotten is {last[1]}.")

Zauważ, jak mało miejsca zajmuje kod i jest bardziej przejrzysty.

Jak to działa?

Pierwszy element listy ranking trafia do zmiennej first, drugi do zmiennej second, trzeci analogicznie. Do zmiennej last przypisany jest ostatni element. Natomiast pytanie brzmi, co oznacza gwiazdka (ang. appendix)?

W tym przypadku określane są konkretne miejsca, w których zależy nam na danych, czyli 1, 2 i 3 miejsce oraz ostatnie. Natomiast reszta jest nie do końca potrzebna, dlatego przypisujemy ją do zmiennej others.

Domyślasz się pewnie, że zmienne first, second, third oraz last to zmienne typu tuple. Natomiast jakiego typu jest zmienna others?

Chwila na zastanowienie…

Masz rację! – To lista krotek. Po prostu wszystkie inne rekordy rankingu trafiają do listy. Źle odpowiedziałeś / odpowiedziałaś? – Nie ma to żadnego znaczenia, bo TERAZ już wiesz 🙂

Tak samo będzie z innymi zmiennymi, w tym przypadku są to tuple, a w innym mogą być liczby, tekst, słowniki lub w zasadzie… cokolwiek 😛

Wnioski i podsumowanie

Skoro już wiemy, jak można to zapisać i jak to działa powiem o kilku korzyściach, idących z używania tego sposobu.

  1. Stosujemy się do Zen of Python. – Beautiful is better than ugly.
  2. Wartości mamy od razu przypisane do zmiennych, które możemy wykorzystać.
  3. Odczyt danych mamy w jednym miejscu. W przypadku składni ranking[0] możemy mieć to rozrzucone po pliku i nie do końca kontrolować przepływ danych, które mogły zostać zmienione w trakcie działania kodu.
  4. Pozbywamy się magic numbers z nawiasów kwadratowych.
  5. Python posiada mechanizmy do tego i nasz kod będzie bardziej Pythonowy.
  6. Dobrze znać różne podejścia, aby wykorzystać to odpowiednie do naszego problemu.

Dzięki za dotarcie do końca! Jeżeli spodobał Ci się wpis, to proszę, przekaż link 1 osobie, której może się on spodobać.

Interesuje Cię jakiś konkretny temat? – Napisz! Tematy cieszące się największym zainteresowaniem pójdą na pierwszy plan :). Inne wpisy z segmentu BiteSize znajdziesz tu.
~ Marek

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *