Java и C ++ требуют, чтобы конструктор базового класса вызывался из-за разметки памяти.
Если у вас есть класс BaseClass
с членом field1
, и вы создаете новый класс, SubClass
который добавляет член field2
, то экземпляр SubClass
содержит пространство для field1
и field2
. Вам нужен конструктор BaseClass
для заполнения field1
, если только вы не требуете, чтобы все наследующие классы повторяли BaseClass
инициализацию в своих собственных конструкторах. И если field1
это private, то наследующие классы не могут инициализироваться field1
.
Python не является Java или C ++. Все экземпляры всех пользовательских классов имеют одинаковую «форму». В основном это просто словари, в которые можно вставлять атрибуты. Перед выполнением любой инициализации все экземпляры всех пользовательских классов практически одинаковы ; это просто места для хранения атрибутов, которые еще не хранятся.
Поэтому для подкласса Python имеет смысл не вызывать конструктор базового класса. Он может просто добавить атрибуты сам, если захочет. Нет места, зарезервированного для данного числа полей для каждого класса в иерархии, и нет разницы между атрибутом, добавленным кодом из BaseClass
метода, и атрибутом, добавленным кодом из SubClass
метода.
Если, как это обычно бывает, на SubClass
самом деле нужно BaseClass
настроить все инварианты, прежде чем он продолжит выполнять свою собственную настройку, тогда да, вы можете просто позвонить BaseClass.__init__()
(или использовать super
, но это сложно и иногда имеет свои проблемы). Но ты не обязан. И вы можете сделать это до, или после, или с другими аргументами. Черт, если бы вы хотели, вы могли бы вызвать BaseClass.__init__
из другого метода полностью, чем __init__
; может быть, у вас происходит какая-то странная ленивая инициализация.
Python достигает этой гибкости, сохраняя простоту. Вы инициализируете объекты, написав __init__
метод, который устанавливает атрибуты self
. Вот и все. Он ведет себя точно так же, как метод, потому что это точно метод. Нет других странных и не интуитивно понятных правил о том, что нужно делать в первую очередь, или о вещах, которые автоматически произойдут, если вы не будете делать другие вещи. Единственная цель, которой он должен служить, - это ловушка для выполнения во время инициализации объекта для установки начальных значений атрибута, и он делает именно это. Если вы хотите, чтобы это делало что-то другое, вы явно пишете это в своем коде.
__init__
метода и даже, возможно, автоматически искать подклассы и декорировать их.