Przeczytaj
Wiemy, jak zdefiniować klasę w języku Python (informacje na ten temat znajdziesz między innymi w e‑materiale Wstęp do programowania obiektowego w języku PythonWstęp do programowania obiektowego w języku Python). Potrafimy też tworzyć obiekt odwołujący się do niej. Zbadamy teraz, w jaki sposób taki obiekt powstaje. Z tego e‑materiału dowiemy się również, jakie czynności są wykonywane podczas usuwania go z przestrzeni nazwprzestrzeni nazw.
Stwórzmy klasę, która będzie przechowywać dane pracowników firmy. Każdy obiekt powinien mieć następujące pola:
imię,
nazwisko,
płeć (kobieta/mężczyzna),
numer telefonu.
Zdefiniujmy klasę Pracownik
. Konstruktor tworzymy przy użyciu specjalnej funkcji dunderdunder o nazwie __init__()
. Dzięki niej utworzymy i zainicjalizujemy pola instancji klasy.
__init__()
pełni rolę konstruktora – specjalnej funkcji dunder, która jest wykonywana podczas tworzenia obiektu. Może ona służyć do inicjowania pól powiązanych z danym obiektem oraz wykonywać inne dowolne operacje związane z nim lub z całą klasą.
Słowo kluczowe self
– wskazuje na konkretny obiekt, który tworzymy.
Utwórzmy obiekt klasy Pracownik
, a następnie wywołajmy metodę pokaz_informacje()
.
Do konstruktora dodamy nowe funkcjonalności. Możemy na przykład skorzystać z domyślnych argumentów. Gdy użytkownik nie wprowadzi płci do konstruktora, możemy domyślnie ustawić ją na "M"
, a w przypadku telefonu domyślą wartością może być None
. Poza tym możemy sprawdzać, czy użytkownik podał poprawne dane. Przykładowo możemy nie pozwalać na ustawienie płci innej niż "M"
i "K"
.
Przetestujmy, jak działa nowy konstruktor:
Jeśli potrzebujemy informacji o skasowaniu obiektu (np. chcemy utworzyć dziennik z odpowiednimi informacjami), mamy do dyspozycji specjalną metodę dunder o nazwie __del__()
. Jest to tzw. destruktor
. Zostaje on wykonany w momencie, w którym obiekt danej klasy przestaje istnieć (jest usuwany z pamięci).
Rozszerzymy klasę Pracownik
o nowe funkcjonalności. Zdefiniujmy w niej słownik przechowujący liczbę osób aktualnie pracujących w firmie. Wywołanie konstruktora tej klasy oznacza wzrost liczby pracowników (np. zatrudnienie nowego pracownika), co powoduje konieczność wzrostu liczby pracowników przechowywanej w stworzonym wcześniej słowniku. Uzyskamy to poprzez inkrementację tej wartości w konstruktorze klasy pod koniec inicjalizacji obiektu (w kodzie przedstawionym poniżej jest za to odpowiedzialna linijka 21). Wywołanie destruktora oznacza działanie przeciwne do konstruktora, czyli spadek liczby pracowników (np. zwolnienie pracownika), co też powoduje konieczność zmiany przechowywanej wartości. W definicji destruktora zawrzemy fragment kodu, który będzie odpowiedzialny za dekrementację przechowywanej w słowniku liczby pracowników. Tworzony przez nas destruktor, oprócz zmniejszenia wartości zmiennej symbolizującej liczbę pracowników (w kodzie poniżej jest za to odpowiedzialna linijka 26), powinien również wyświetlić komunikat, jaki obiekt jest usuwany. Oprócz konstruktora i destruktora dodamy również funkcję wypisującą na standardowe wyjście aktualną liczbę pracowników, funkcję tę wykorzystamy również w destruktorze do wyświetlenia zmodyfikowanego stanu zmiennej.
Przetestujemy teraz, jak działa licznik osób w firmie, a także usuwanie obiektów pracowników, wykorzystując funkcję del()
.
Wynik działania programu:
Jeżeli po uruchomieniu powyższego kodu, pozwolimy mu zakończyć działanie bez przerywania (np. punktami przerwań w trybie debug kompilatora), zauważymy, że na standardowym wyjściu oprócz oczekiwanych komunikatów pojawią się również następujące:
Wystąpienie wspomnianego wcześniej komunikatu zależy od używanego interpretera. W przypadku używania interpretera IDLE komunikat się nie pojawi, jednak jeśli używasz interpretera PyCharm – tak.
Jest to spowodowane faktem, że pod koniec wykonywania skryptu wciąż istniejące obiekty wychodzą z zasięgu, co powoduje, że ich destruktory zostają wywołane podczas działania odśmiecaczaodśmiecacza.
Bez jawnie zdefiniowanego konstruktora obiekt zostanie utworzony za pomocą konstruktora domyślnego stosowanego w takich sytuacjach przez język Python do tworzenia obiektów. Konstruktor taki nie robi z obiektem nic, poza umożliwieniem jego stworzenia (nie zmienia jego zmiennych wewnętrznych i nie wywołuje metod).
Bez jawnie zdefiniowanego destruktora język Python zastosuje do obsługi danego obiektu destruktor domyślny, który wykona jedynie podstawowe zadania destruktora.
Konstruktor i destruktor mogą zawierać kod odnoszący się do elementów konkretnego obiektu oraz do współdzielonych elementów klasy.
Konstruktora używamy, aby zainicjować pola nowego obiektu klasy.
Konstruktor może zawierać dowolny blok kodu.
Destruktora używamy, jeśli chcemy wykonać blok kodu w momencie usuwania obiektu z pamięci.
Słownik
(ang. double under) funkcja, metoda lub pole specjalnego przeznaczenia w języku Python
(ang. garbage collector) aplikacja odpowiadająca za automatyczne czyszczenie pamięci, gdy znajdują się w niej niepotrzebne już dane
(ang. namespace) pakiet nazw zmiennych wraz z ich wartościami, przechowywanych w postaci słownika dict
; przestrzenie nazw są przypisane m.in. do funkcji, modułów, klas