Java та C ++ вимагають, щоб конструктор базового класу викликався через компонування пам'яті.
Якщо у вас є клас BaseClassз членом field1, і ви створюєте новий клас, SubClassякий додає член field2, то екземпляр SubClassмістить простір для field1і field2. BaseClassДля заповнення вам потрібен конструктор field1, якщо вам не потрібні всі класи успадковування для повторення BaseClassініціалізації в їхніх власних конструкторах. А якщо field1це приватне, то класи успадкування не можуть ініціалізуватися field1.
Python - це не Java або C ++. Усі екземпляри всіх визначених користувачем класів мають однакову "форму". Вони в основному просто словники, в які можна вставити атрибути. Перед тим, як було зроблено будь-яку ініціалізацію, всі екземпляри всіх визначених користувачем класів майже точно однакові ; вони просто місця для зберігання атрибутів, які ще не зберігаються.
Тому для підкласу Python є ідеальним не називати його конструктор базового класу. Він може просто додати самі атрибути, якщо цього захоче. Немає місця, відведеного для заданої кількості полів для кожного класу в ієрархії, і немає різниці між атрибутом, доданим кодом від BaseClassметоду, і атрибутом, доданим кодом з SubClassметоду.
Якщо, як прийнято, SubClassнасправді хочуть створити всі BaseClassінваріанти, перш ніж він продовжить робити власні налаштування, то так, ви можете просто зателефонувати BaseClass.__init__()(або використовувати super, але це складне і іноді має свої проблеми). Але не потрібно. І ви можете це робити до, або після, або з різними аргументами. Пекло, якби ти хотів, ти можеш зателефонувати BaseClass.__init__з іншого методу цілком, ніж __init__; можливо, у вас відбувається якась химерна лінива ініціалізація.
Python досягає цієї гнучкості шляхом простоти речей. Ви ініціалізуєте об'єкти, записавши __init__метод, який встановлює атрибути self. Це воно. Він поводиться точно як метод, тому що це саме метод. Немає інших дивних і неінтуїтивних правил щодо речей, які потрібно зробити спочатку, або речей, які автоматично відбудуться, якщо ви не зробите інших речей. Єдина мета, якій вона повинна служити, - це гак для виконання під час ініціалізації об'єкта для встановлення початкових значень атрибутів, і він робить саме це. Якщо ви хочете, щоб це робило щось інше, ви явно записуєте це у свій код.
__init__методу і навіть, можливо, автоматично шукати підкласи та прикрашати їх.