2024-10-29

Myśląc o Pythonie: Mutowalność danych

Dziś powrócimy do tematu, który czasem mogło udać Nam się liznąć już w niektórych artykułach. Przykladem mógł być artykuł o listach, bowiem są one tworem powiązanym z dzisiejszym tematem posta - mutowalność. Mogło się to przewinąć na matematyce, razem z kombinatoryką. Komu więc wydało się to pojęcie znajome, to pewnie ma dobre skojarzenia 😉

W Pythonie mamy też mutowalność, którą można określić jako zmienność. Jest to kolejna ważna koncepcja. Obiekt może być mutowalny, albo nie. Upraszczając, można powiedzieć, że pewne obiekty (jak listy) można zmieniać. Innych natomiast zmienić nie możemy - jak powstały, tak umrą w tej samej formie.

Mutowalność w podstawach

Rozpocznijmy może od pokazania sobie przykładu czegoś mutowalnego, o czym już wspominaliśmy. Jest to oczywiście lista. Utwórzmy więc jakąś listę.

mutowalność - zacznijmy od prostej listy

Oczywiście jak widzimy możemy sobie sprawdzić typ listy, by potwierdzić, że żaden inny podejrzany typ się nie podszywa pod Naszą listę. Możemy też wyświetlić zawartość listy, nic nowego. Możemy też, co także nie jest nową informacją, dodać coś do listy, albo zmienić element - czyli ją zmienić. Dowodzi to jej mutowalności.

mutowalność - zmieniamy element listy i sprawdzamy czy to ta sama lista

Tutaj poprzez zmianę elementu na liście, a także sprawdzenia id przed i po tej operacji, udowodniliśmy, że to ta sama lista. Innymi słowy, zmieniliśmy listę, a ona pozostała tym samym. Inaczej sprawa ma się z takim tuple.

Niemutowalność

Tuple w przeciwieństwie do listy jest niemutowalne. Znaczy to, że nie możemy go zmienić. Próbwa zmiany tupli będzie skutkowała błędem, jak poniżej.

mutowalność - niemutowalna tuple i błąd przy próbie jej zmiany

Po uruchomieniu kodu próbującego zmienić coś w tupli, otrzymujem błąd TypeError. Informacja zawarta w komunikacie błędu informuje Nas, że tupla nie obsługuje przypisania. Nie możemy zatem przypisać nowej wartości elementowi. Tupla będzie przechowywała tylko te wartości, jakie zostały do niej dodane w czasie tworzenia.

Możemy oczywiście stworzyć nową tuplę, która będzie zawiarała po prostu te same wartości, i tą jedną już po modyfikacji. W takim wypadku będzie to jednak inny obiekt, inna tupla. Kolejną ciekawą rzeczą, jest to, że jesteśmy w stanie trochę nagiąć zasady i stworzyć tuplę, którą w pewnym stopniu można zmieniać. Jak to? Zobaczmy poniższy kod.

mutowalność - tupla obchodząca ograniczenia niemutowalności własnego typu

Jak widzimy powyżej, najpierw tworzymy listę by następnie umieścić ją w tupli. Mamy więc tuplę, czyli obiekt niemutowalny. Wewnątrz tupli jest natomiast lista - obiekt mutowalny. Zatem nie możemy zmienić tupli, ale za to zmieniamy listę, która jest w tupli. Takie działanie jest możliwe i nie powoduje błędu. Jak widać po zmianie listy w tupli, widzimy zmianę na ekranie. Spróbuj też na zadanie dodać tuplę z tuplą. Co się stanie? Powstanie nowa tupla?

Mutowalność i niemutowalność przydają się w różnych sytuacjach. Jeśli chcemy obiekt, który będzie dynamicznie się zmieniał, postawimy na coś mutowalnego. Jeśli chcemy mieć natomiast pewność, że zawartość czegoś przypadkowo nie ulegnie zmianie, a na dodatek będzie to szybsze - wybierzemy obiekt niemutowalny. Obiekt niemutowalny wpływa korzystnie na wydajność, ale w przypadku chęci jego zmiany, musimy utworzyć nowy na podstawie starego - co jest operacją stosunkowo wolną. Inaczej sytuacja ma się oczywiście z obiektami mutowalnymi. Każde z rozwiązań ma swoje wady i zalety, które musimy brać pod uwagę.

Inne typy pod względem mutowalności

Prócz sztandarowego przykładu list i tuple, mamy w Pythonie też inne typy. I tutaj przykładowo mamy taki string, który jest typem niemutowalnym. Nie możemy go zmieniać, a po prostu tworzyć nowy na podstawie starego.

mutowalność - typ string

Jak widzimy powyżej, nie możemy zmienić Ali w Elę próbując podmienić znaki w taki sposób. Pewnie dlatego stworzono funkcję replace. Możemy po prostu użyć tej funkcji, albo zrobić nowy napis, jeśli koniecznie chcemy zamienić ciąg 'Ala' na 'Ela'.

Niemutowalny też jest typ liczbowy. Integer nie ma indexu, więc nie możemy nawet w taki sam sposób jak poprzednie zmieniać tego typu, jak widzisz poniżej.

mutowalność - problem z intami

W przypadku typu int jednak jest inna możliwość. Możemy po prostu dodać do niego coś. Przykładowo możliwe jest użycie inkrementacji, co przecież dodaje jedynkę, czyli zmienia wartość.

mutowalność - inkrementacja w intach

Jednak jak widzisz, zmiana wartości liczby całkowitej, po prostu tworzy nowy obiekt, na który wskazuje zmienna. Nie jest to zatem typ mutowalny, a może tylko sprawiać takie wrażenie.

Jak widzimy, nie wszystko jest takie jak się wydaje na pierwszy rzut oka. Warto zatem sprawdzać czy to co Nam się wydaje, rzeczywiście jest właśnie takie jak to postrzegamy. Teraz już o tym wiesz, jesteś też poinformowany jak się bronić przed oszustwem i sprawdzić co jest mutowalne, a co nie. Korzystaj mądrze 😉

One comment on “Myśląc o Pythonie: Mutowalność danych”

Dodaj komentarz

linkedin facebook pinterest youtube rss twitter instagram facebook-blank rss-blank linkedin-blank pinterest youtube twitter instagram