2024-10-08

Myśląc o Pythonie: Atrybuty klasy

Z racji choroby mam trochę poślizg z postami, ale dziś mam dla Was kolejny post.. Dziś porozmawiamy o atrybutach klas, które są istotną koncepcją gdy przykładowo chcielibyśmy zrobić licznik instancji. Czyli licznik, który zlicza ile obiektów danej klasy zostało utworzonych- zwiększający się przy każdym utworzeniu obiektu.

Mówiliśmy wcześniej o metodach i właściwościach, czyli o elementach przypisanych do konkretnej instancji. Innymi słowy, charakteryzujących daną instancje, bo dla każdej mogą mieć inne wartości. Przykładowo właściwość / atrybut imie, przypisywany w konstruktorze, moze być inny dla każdej istatncji.

demonstacja atrybutów różnych dla poszczególnych obiektów, bez atrybutu klasy

Myślę, że juź doskonale wiesz, jak zachowa się powyższy kod, ale dla formalności. Tworzymy klasę Person, która ma atrybut name i surname, a później kolejno tworzymy trzy instancje: Jan, Anna i Piotr. Na końcu wyświetlamy imiona wszystkich obiektów. Wynikiem będzie oczywiście wyswietlenie kolejno tekstu i imion, by wiedzieć dokładnie jaka instancja jak się nazywa.

Wiele instancji, jeden atrybut

Skoro już pamiętamy jak działają atrybuty instancji - dla każdej jest to osobny atrybut, z osobną wartością, możemy zastanowić się, co jeśli chcemy jedną wartość dla wszystkich. Nie będziemy oczywiście ustawiać ręcznie w każdej instancji atrybutu, który będzie powieleniem i jakoś ustawiać każdy na np. taką samą wartość. Rozwiązaniem też nie będzie sytuacja gdy w konstruktorze utworzymy atrybut z na sztywno przypisana wartością - nie możemy jej zmienić dla wszystkich na raz.

Mamy więc pewien problem, bo każdy obiekt ma swoje atrybuty, swoje dane. Wszyscy ludzie nazywają się inaczje, mają inną osobowość, przeczłość i inne cechy. Oczywiście każdy ma np. nogę, ale każdy ma swoją własną, to nie jest ta sama noga dla wszystkich. Tak samo Nasze obiekty. Tutaj przyjdzie Nam na pomoc właśnie atrybut klasy.

Będzie to coś wspólnego na poziomie klasy, do czego dostęp będzie miał każdy obiekt, ale nie będzie to osobny atrybut dla każdego. Jeden atrybut dla wszyskich - to rozwiązanie problemu 'niejednolitości'. Każdy wie, że istnieje jeden przykładowo licznik ludzi i każdy może z niego brać informacje o populacji. Każdy kolejny człowiek, rodząc się będzie też zwiększać licznik o jeden. Gdyby użyć poznanych atrybutów, każdy człowiek miałby po prostu osobno jakiś numer - nie byłoby jednego numeru, który zmieniać mogą kolejne narodziny.

Konkretne rozwiązania - implementacja atrybutu klasy

U Nas będzie to licznik utworzonych obiektów. Python posiada mechanizmy pozwalające to zaimplementować. Nie jest to, jak w innych językach, statyczna właściwość - tutaj jest to atrybut klasy. Pozwala Nam on przejść z poziomu 'tworzenia zmiennej' na poziomie instancji, do robienia tego niejako na poziomie klasy.

użycie koncepcji atrybut klasy

Nasz kod uległ drobnej zmiane, dodaliśmy dodatkową zmienną, bezpośrednio w klasie. Jest to wlaśnie atrybut klasy, który będzie Nam służył do zliczania kolejnych obiektów utworzonych na podstawie tej klasy. Aby odwołać się do atrybutu klasy, podajemy nazwę klasy, a następnie właściwość po kropce. Jest to podobna stuacja jak z wywoływaniem metod lub ręcznym przypisywaniem wartości atrybutów instancji. Tylko właśnie tutaj jest to robione na poziomie klasy.

Atrybut klasy powyżej jest zwiększany w konstruktorze - czyli przy konstrukcji każdego obiektu jest dodawane jeden do jego aktualnej wartości (która jest trzymana dla całej klasy). Zatem każdy kolejny obiekt zwiększa licznik, zatem Nasz powinien wynosić kolejno 1,2 i 3.

efekt działania prostej imprementacji atrybutu klasy

Jak widzimy dokładnie taki jest efekt. Instrukcje wyświetlające wartość na ekran właśnie to Nam uwidaczniają.

atrybut klasy w instancji

Python ma dość ciekawą specyfikę również tutaj, możemy bowiem dobrać się też do atrybutu klasy, który utworzyliśmy, ale na poziomie instancji. Co to znaczy? Właśnie tyle, że Nasze obiekty mają od teraz dodatkową właściwość - population. Zobaczmy jak to wygląda.

atrybut klasy na poziomie instancji

Co zobaczymy w efekcie działania powyższego kodu? Sprawa wydaje się ciekawa, ponieważ population na poziomie instancji zdaje się niczym nie różnić od population na poziomie całej klasy. Tutaj bowiem po utworzeniu obiektu zobaczymy cyfrę jeden. Wydaje się, że population w p1 odziedziczyło wartość po 'klasowym' population. Zobaczmy.

atrybut klasy efket wyświetlenia atrybutu klasy z instancji

I mamy przed tworzeniem wartość atrybutu klasy zero, jak zapisano w definicji klasy, ale po utworzeniu obiektu i sprawdzeniu p1.population mamy jedynkę. I również na poziomie klasy zobaczymy jeden.

atrybut klasy i dziwne zachowanie

Nie jest to jednak to samo jeden, bo jeśli p1.population przypiszemy przykładowo wartość 10, to atrybut klasy wartości nie zmieni.

Widzisz? Całkiem ciekawe zachowanie. Utworzyły się dwie niejako rozdzielne właściwości. Co by się stało gdybyśmy przykładowo zmienili wartość atrybutu Person.population na 10 i utworzyli kolejny obiekt. Jak wtedy będą wyglądały wartości tych atrybutów? Domyślasz się? Sprawdź pisząc kod i sam potestuj 😉 Praktyka jest kluczowa!

Dodaj komentarz

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