W programowaniu jest obecnych wiele typów danych, które pomagają kategoryzować i rozróżniać różne rzeczy, jakie odzwierciedlamy w kodzie. Takie typy danych są trochę inaczej obecne w różnych językach. W Pythonie, również mamy ich trochę. Python, to język, który stoi typami danych nazywanymi zbiorczo kolekcjami. W kilku ostatnich postach mówiliśmy o takich kolekcjach. Listy, bo o nich mowa, są jednym z członków tej zacnej rodziny. Kolejnym są tak zwane Tuples. Tuple w Ptyhonie, ale nie tylko, to po polsku tuples nazywa się krotkami, ale lepiej zostańmy przy angielskiej nazwie.
Tuples ogółem
Tuples są, podobnie jak listy zbiorami wartości, ale oczywiście nie jest są tym samym typem. Jest to inny typ, który co prawda składuje kolekcje wartości, ale w trochę odmienny sposób od listy. Pierwszą różnicą jest to, że składnia jest inna. Znaczy to, że nie używamy nawiasów kwadratowych jak w listach, zamiast tego mamy tutaj do czynienia z nawiasami zwykłymi. Czy inaczej mówiąc nawiasami okrągłymi.
Podobnie jak listy tuples mogą przechowywać różne wartości, także posiadają indeks dla każdej z pozycji. Fakt, że są indeksowane tak samo jak listy, pozwala się odwołać do pojedynczej pozycji. Odwołanie takie następuje tak samo jak w listach.
W stosunku do list, mamy tutaj także jedną sporą różnicę. Mianowicie tuples nie są kolekcją mutowalną. Ich niemutowalność oznacza, że wartości nie można modyfikować. Jeśli już wprowadzimy, na początku, wszystkie wartości do naszego obiektu typu tuple. Nie będziemy mogli już ich zmodyfikować, będzie jedynie możliwy odczyt. Jest to fundamentalna różnica w porównaniu z listą. Która jest mutowalna i w każdej chwili możemy coś do niej dodać, usunąć lub coś zmienić.
Tuple jako kolekcja, w zbliżeniu
Obiektu typu taple używamy wszędzie tam gdzie jest nam potrzebny zestaw niemutowalnych wartości. Jeśli chcemy mieć gwarancję, że te wartości w żaden sposób przez inne części kodu nie zostaną zmienione. Przy okazji należałoby też nadmienić, że tuple są szybsze, wydajniejsze. Dostęp do informacji w nich zawarty jest szybszy, co widać w efekcie skali, ale o tym może kiedy indziej.
Na poniższym obrazku mamy skrótowo wymienione cechy i charakterystykę tupli.

Przechodząc do praktyki, wróćmy do wspomnianych nawiasów. Jak mówiłem, tutaj zamiast nawiasów kwadratowych użyjemy okrągłych. I tak oto, zamieniając nawiasy w naszej tablicy, możemy zrobić z niej tuplę.

Natomiast nie jest to jedyny sposób na, jak widzimy wyżej, utworzenie pustej tupli. Bowiem wielu nie wie, że tupla nie stoi samymi nawiasami, bo to nie do końca o nie chodzi. Popatrzmy na poniższy przykład.

No i właśnie. Nie użyłem nawiasów, a mimo to uzyskujemy typ tuple. O co więc chodzi z tymi tuplami. Tutaj potrzebujemy nawiasów, ale jednak nie? Sprawa opiera się na tym, że całe środowisko przyzwyczaiło się i tak też się utarło, że do tupli używa się nawiasów okrągłych. I w zasadzie to jest dobra praktyka, ale zapomniano trochę, że nie musi tak być.
Tupla bowiem, jest kolekcją, której wystarczy sam fakt tego, że zawiera wartości. Każda z takich wartości powinna być wymieniona po przecinku. Z tym, że, jak widać powyżej. Sama jedna, samotna wartość, a po niej przecinek, jest wystarczająca do powstania tupli. Jest to dobra ciekawostka na rozmowę rekrutacyjną.
Tuple w Pythonie i ich niemutowalność
Tuple w Pythonie są czymś, co jest dość osobliwym zjawiskiem. Bo możemy sobie stworzyć tuple, jest ona szybsza w dostępie i ogólne nie można jej zmieniać, można tylko co najwyżej utworzyć jej nową kopię, która będzie modyfikacją oryginału. Natomiast tupla może przechowywać różne wartości, więc co gdyby jednym z jej elementów była tablica? Ciekawe pytanie, ale od początku.
Brak mutowalności tuple objawia się przykładowo tym, że odowłanie się, za pomocą indeksu, do jakiejś wartości z tupli. I próba przypisania jej nowej wartości zwróci błąd.

W powyższym kodzie tworzymy sobie tuple o nazwie mojaTupla, przypisujemy jej jakiś zbiór wartości, a później wyświetlamy wartość znajdującą się na indeksie o numerze zero. Natomiast mamy dodatkową linijkę poniżej. Linijkę, która próbuje umieścić na pozycji zajętej już przez jedynkę, nową wartość. Może jej się tam nie podoba ta jedynka, może ją wkurza, ale... co ważne - nie uda się jej przypisać. Linijka trzecia w powyższym kodzie wygeneruje bowiem błąd widoczny poniżej.

Pożywszy błąd mówi Nam, że obiekt typu tuple w Pythonie, nie obsługuje przypisywania. Jest to właśnie potwierdzenie tego, że nie możemy zmienić wartości, którą raz już umieściliśmy w naszej tupli.
Tuple i jej różne wartości
Oczywiście, jak już wspomnieliśmy. W tupli można, tak jak w liście, przechowywać różne wartości. Mogą to być cyfry, jak powyżej, ale także stringi czy wartości typu boolean. Zobaczmy sobie na przykład.

Jak widzimy powyżej, jakiś śmieszek, dopisał Nam do naszej tupli wartości różnego typu. Dopisanie wspomnianych wartości typu string czy boolean nie powoduje żadnego błędu, a zawartość tupli jest poprawnie wyświetlana.
Ciekawiej robi się jeśli do tupli dodamy sobie taki typ jak lista. Ponieważ lista, z natury swej, jest mutowalna, więc można ją zmieniać. Tupli natomiast zmieniać nie można, jest niemutowalna. Jak myślisz co się stanie jak dodamy mutowalną listę do niemutowalnej tupli? (Wszystko wybuchnie?) Zacznijmy od wdrożenia Naszego niecnego planu w życie.

Jak widzimy powyżej, do naszej tupli, i to na pierwszym miejscu (albo zerowym), dołączyła lista. Mamy nawet potwierdzeniem, którego dostarcza Nam funkcja type. Obiekt w tupli ewidentnie jest listą, co więcej nic nie wybuchło :/
No więc mamy sobie niemutowalną tuple, a w niej mutowalną listę. Może teraz da się coś zmienić w tupli? Zobaczmy, spróbujmy zmienić, sobie listę na coś innego.

No i klops. Jak widzimy przy próbie zmiany, tuple w Pythonie, nawet z użyciem potężnej mocy magicznej, nie dają sobie podmienić pierwszego elementu tupli na coś innego, nawet mimo tego, że jest to lista. No, ale przecież tuple są niemutowalne, więc mogliśmy się tego spodziewać. Działanie 'na poziomie ' tupli nie Nam nie da.
Odwołanie wewnętrzne w kolekcji
Mutowalne są listy, nie tuple w Pythonie, więc może spróbujmy działać wewnątrz samej listy, która znalazła przytulny domek w naszej tupli. No to spróbujmy napisać kod odwołujący się do indeksu o numerze 0, w Naszej liście.

Jak zauważamy (lub nie od razu), nasz kod trochę się zmienił. Chodzi tutaj dokładnie o linię numer 3. Jest tam bowiem dodatkowy indeks. Jednym słowem odwołujemy się do pozycji na indeksie 0 w naszej tupli, a później wchodząc głębiej, odwołujemy się do pozycji na indeksie 0. Robimy to jednak w ramach pozycji zerowej naszej tupli (no dobra, to było więcej niż jedno słowo).
W efekcie edytujemy pierwszą wartość, pierwszej wartości tupli. No i co się stanie jak to uruchomimy?

Wspomniany kod nie wygenerował nam błędu. Wyświetlił się tylko efekt działania linii drugiej, czyli wiemy, że Nasza tupla jest nadal tuplą. Zatem możemy wyświetlić zawartość pierwszego elementu tablicy, będącej pierwszym elementem tupli. Na pewno już wiesz jak wyświetlić zawartość takiego elementu 😉
Przetwarzanie za pomocą for
Nikogo oczywiście nie zdziwi, jak powiem (a raczej napiszę), że tupla - skoro też jest kolekcją - może być przetwarzana przez pętlę for. Która może po niej, najzwyczajniej w świecie, iterować. Zobaczmy więc krótki i podstawowy przykład jak to robić.

Jak widzimy wyżej pętla for po prostu przyjmuje nazwę dla pojedynczego elementu kolekcji item, a w każdym przejściu wyświetla kolejną pozycję. Która znajduje się pod tym "itemem", czyli kolejną pozycję z tupli, po której iteruje. Nie jest to chyba żadne zdziwienie, jeśli jest to zapraszam do tego artykułu.
Polecam pobawić się tuplami w Pythonie, a w przyszłym poście opowiemy sobie więcej o krotkach i o tym co można znimi robić.

[…] poprzednim odcinku zaczęliśmy sobie mówić o tuplach w Pythonie. Dziś zatem pociągniemy sobie ten temat dalej. Co wiemy o takiej konstrukcji jak […]