Zanurkuj w Pythonie/Definiowanie klas
Z Wikibooks, biblioteki wolnych podręczników.
[edytuj] Definiowanie klas
Python jest całkowicie zorientowany obiektowo: możemy definiować własne klasy, dziedziczyć z własnych lub wbudowanych klas, a także tworzyć instancje zdefiniowanych przez siebie klas.
Tworzenie klas w Pythonie jest proste. Podobnie jak z funkcjami, nie używamy oddzielnego interfejsu definicji. Po prostu definiujemy klasę i zaczynamy ją implementować. Klasa w Pythonie rozpoczyna się słowem kluczowym class, po którym następuje nazwa klasy, a następnie w nawiasach okrągłych umieszczamy, z jakich klas dziedziczymy.
class Nicosc(object): #(1)
pass #(2) (3)
- Nazwa tej klasy to
Nicosc, a klasa ta dziedziczy z wbudowanej klasyobject. Nazwy klas są zazwyczaj pisane przy użyciu wielkich liter np.KazdeSlowoOdzieloneWielkaLitera, ale to kwestia konwencji nazewnictwa; nie jest to wymagane. - Klasa ta nie definiuje żadnych metod i atrybutów, ale żeby kod był zgodny ze składnią Pythona, musimy coś umieścić w definicji, tak więc użyliśmy
pass. Jest to zastrzeżone przez Pythona słowo, które mówi interpreterowi "przejdź dalej, nic tu nie ma". Instrukcja ta nie wykonuje żadnej operacji i powinniśmy stosować ją, gdy chcemy zostawić funkcję lub klasę pustą. - Prawdopodobnie zauważyliśmy już, że elementy w klasie są wyszczególnione za pomocą wcięć, podobnie jak kod funkcji, instrukcji warunkowych, pętli itp. Pierwsza nie wcięta instrukcja nie będzie należała już do klasy.
Instrukcja pass w Pythonie jest analogiczna do pustego zbioru nawiasów klamrowych ({}) w Javie lub w języku C++. |
W prawdziwym świecie większość klas definiuje własne metody i atrybuty. Jednak, jak można zobaczyć wyżej, definicja klasy, oprócz swojej nazwy z dodatkiem object w nawiasach, nie musi nic zawierać. Programiści C++ mogą zauważyć, że w Pythonie klasy nie mają wyraźnie sprecyzowanych konstruktorów i destruktorów. Pythonowe klasy mają coś, co przypomina konstruktor -- metodę __init__.
FileInfoclass FileInfo(dict): #(1)
- Jak już wiemy, klasy, z których chcemy dziedziczyć wyszczególniamy w nawiasach okrągłych, które z kolei umieszczamy bezpośrednio po nazwie naszej klasy. Tak więc klasa
FileInfodziedziczy z wbudowanej klasydict, a ta klasa, to po prostu klasa słownika.
Python obsługuje dziedziczenie wielokrotne. Wystarczy w nawiasach okrągłych, umiejscowionych zaraz po nazwie klasy, wstawić nazwy klas, z których chcemy dziedziczyć i oddzielić je przecinkami np. class klasa(klasa1,klasa2).
[edytuj] Inicjalizowanie i implementowanie klasy
Ten przykład przedstawia inicjalizację klasy FileInfo za pomocą metody __init__.
class FileInfo(dict):
u"przechowuje metadane pliku" #(1)
def __init__(self, filename=None): #(2) (3) (4)
- Klasy mogą (a nawet powinny) posiadać także notkę dokumentacyjną, podobnie jak moduły i funkcje.
- Metoda
__init__jest wywoływana bezpośrednio po utworzeniu instancji klasy. Może kusić, aby nazwać ją konstruktorem klasy, co jednak nie jest prawdą. Metoda__init__wygląda podobnie do konstruktora (z reguły__init__jest pierwszą metodą definiowaną dla klasy), działa podobnie (jest pierwszym fragmentem kodu wykonywanego w nowo utworzonej instancji klasy), a nawet podobnie brzmi (słowo "init" sugeruje, że jest to konstruktor). Niestety nie jest to prawda, ponieważ obiekt jest już utworzony przed wywołaniem metody__init__, a my już otrzymujemy poprawną referencję do świeżo utworzonego obiektu. Jednak__init__w Pythonie, jest tym co najbardziej przypomina konstruktor, a ponadto pełni prawie taką samą rolę. - Pierwszym argumentem każdej metody znajdującej się w klasie, włączając w to
__init__, jest zawsze referencja do bieżącej instancji naszej klasy. Według powszechnej konwencji, argument ten jest zawsze nazywanyself. W metodzie__init__selfodwołuje się do właśnie utworzonego obiektu; w innych metodach klasy,selfodwołuje się do instancji, z której wywołaliśmy daną metodę. Mimo, że musimy wyraźnie określić argumentselfpodczas definiowania metody, ale nie określamy go w czasie wywoływania metody; Python dodaje go automatycznie. - Metoda
__init__może posiadać dowolną liczbę argumentów i podobnie jak w funkcjach, argumenty mogą być zdefiniowane z domyślnymi wartościami (w ten sposób stają się argumentami opcjonalnymi). W tym przypadku argumentfilenamema domyślną wartość określoną jakoNone, który jest Pythonową pustą wartością.
FileInfo
class FileInfo(dict):
u"przechowuje metadane pliku"
def __init__(self, filename=None):
dict.__init__(self) #(1)
self["plik"] = filename #(2)
#(3)
- Niektóre języki pseudo-zorientowane obiektowo jak Powerbuilder posiadają koncepcję "rozszerzania" konstruktorów i innych zdarzeń, w których metoda należąca do nadklasy jest wykonywana automatycznie przed metodą podklasy. Python takiego czegoś nie wykonuje; zawsze należy wyraźnie wywołać odpowiednią metodę należącą do przodka klasy.
- Klasa ta działa podobnie jak słownik (w końcu z niego dziedziczymy), co mogliśmy zauważyć po spojrzeniu na tę linię. Przypisaliśmy argument
filenamejako wartość klucza"plik"w naszym obiekcie. - Zauważmy, że metoda
__init__nigdy nie zwraca żadnej wartości.
[edytuj] Kiedy używać self i __init__
Podczas definiowania metody pewnej klasy, musimy wyraźnie wstawić self jako pierwszy argument każdej metody, włączając w to __init__. Kiedy wywołujemy metodę z klasy nadrzędnej, musimy dołączyć argument self, ale jeśli wywołujemy metodę z zewnątrz, nie określamy argumentu self, po prostu go pomijamy. Python automatycznie wstawi odpowiednią referencję za nas. Na początku może się to wydawać trochę namieszane, jednak wynika to z pewnych różnic, o których jeszcze nie wiemy [1].
Przypisy
- ↑ Wynika to z różnic pomiędzy metodami instancji klasy (ang. bound method), a metodami samej klasy (ang. unbound method)