Java i C ++ wymagają wywołania konstruktora klasy bazowej ze względu na układ pamięci.
Jeśli masz klasę BaseClass
z członkiem field1
i tworzysz nową klasę, SubClass
która dodaje członka field2
, to wystąpienie SubClass
zawiera miejsce na field1
i field2
. Potrzebujesz konstruktora BaseClass
do wypełnienia field1
, chyba że chcesz, aby wszystkie klasy dziedziczące powtarzały BaseClass
inicjalizację we własnych konstruktorach. A jeśli field1
jest prywatny, dziedziczenie klas nie może zostać zainicjowane field1
.
Python to nie Java ani C ++. Wszystkie wystąpienia wszystkich klas zdefiniowanych przez użytkownika mają ten sam „kształt”. Są to po prostu słowniki, w których można wstawiać atrybuty. Przed wykonaniem jakiejkolwiek inicjalizacji wszystkie wystąpienia wszystkich klas zdefiniowanych przez użytkownika są prawie dokładnie takie same ; to tylko miejsca do przechowywania atrybutów, które jeszcze nie przechowują.
Dlatego też dla podklasy Pythona ma sens, aby nie wywoływać konstruktora klasy bazowej. Mógłby po prostu dodać atrybuty, gdyby chciał. Nie ma miejsca zarezerwowanego dla danej liczby pól dla każdej klasy w hierarchii i nie ma różnicy między atrybutem dodanym przez kod z BaseClass
metody a atrybutem dodanym przez kod z SubClass
metody.
Jeśli, co jest powszechne, SubClass
faktycznie chce mieć wszystkie BaseClass
niezmienniki ustawione przed przystąpieniem do własnych dostosowań, to tak, możesz po prostu zadzwonić BaseClass.__init__()
(lub użyć super
, ale jest to skomplikowane i czasami ma swoje własne problemy). Ale nie musisz. Możesz to zrobić przed, po lub z różnymi argumentami. Do diabła, gdybyś chciał, mógłbyś wywołać the BaseClass.__init__
z innej metody całkowicie niż __init__
; może masz jakieś dziwne, leniwe inicjowanie.
Python osiąga tę elastyczność dzięki prostocie. Obiekty inicjalizujesz, pisząc __init__
metodę, która ustawia atrybuty self
. Otóż to. Zachowuje się dokładnie jak metoda, ponieważ jest dokładnie metodą. Nie ma innych dziwnych i nieintuicyjnych zasad dotyczących rzeczy, które trzeba zrobić najpierw lub rzeczy, które wydarzy się automatycznie, jeśli nie zrobisz innych rzeczy. Jedynym celem, jaki musi spełniać, jest być punktem zaczepienia do wykonania podczas inicjalizacji obiektu w celu ustawienia początkowych wartości atrybutów, i właśnie to robi. Jeśli chcesz, aby robił coś innego, napisz to wyraźnie w swoim kodzie.
__init__
metodę, a nawet może automatycznie wyszukać podklasy i je ozdobić.