Java e C ++ richiedono che venga chiamato un costruttore di classe base a causa del layout di memoria.
Se hai una classe BaseClasscon un membro field1e crei una nuova classe SubClassche aggiunge un membro field2, un'istanza di SubClasscontiene spazio per field1e field2. È necessario BaseClasscompilare un costruttore field1, a meno che non sia necessario che tutte le classi ereditarie ripetano BaseClassl'inizializzazione nei propri costruttori. E se field1è privato, l'ereditarietà delle classi non può essere inizializzata field1.
Python non è Java o C ++. Tutte le istanze di tutte le classi definite dall'utente hanno la stessa "forma". Sono fondamentalmente solo dizionari in cui è possibile inserire attributi. Prima di qualsiasi inizializzazione, tutte le istanze di tutte le classi definite dall'utente sono quasi identiche ; sono solo luoghi in cui archiviare attributi che non sono ancora stati archiviati.
Quindi ha perfettamente senso che una sottoclasse Python non chiami il suo costruttore di classe base. Potrebbe semplicemente aggiungere gli attributi stessi se lo desiderasse. Non c'è spazio riservato per un determinato numero di campi per ogni classe nella gerarchia e non c'è differenza tra un attributo aggiunto dal codice da un BaseClassmetodo e un attributo aggiunto dal codice da un SubClassmetodo.
Se, come è comune, in SubClassrealtà vuole avere tutti BaseClassgli invarianti impostati prima che continui a fare la propria personalizzazione, allora sì, puoi semplicemente chiamare BaseClass.__init__()(o utilizzare super, ma è complicato e ha i suoi problemi a volte). Ma non devi. E puoi farlo prima, o dopo, o con diversi argomenti. Inferno, se volevi, potresti chiamare il BaseClass.__init__da un altro metodo interamente di __init__; forse hai qualcosa di bizzarro inizializzazione pigra in corso.
Python raggiunge questa flessibilità mantenendo le cose semplici. Inizializzi gli oggetti scrivendo un __init__metodo che imposta gli attributi self. Questo è tutto. Si comporta esattamente come un metodo, perché è esattamente un metodo. Non ci sono altre regole strane e non intuitive sulle cose che devono essere fatte prima, o cose che accadranno automaticamente se non fai altre cose. L'unico scopo che deve servire è quello di essere un hook da eseguire durante l'inizializzazione dell'oggetto per impostare i valori degli attributi iniziali, e fa proprio questo. Se vuoi che faccia qualcos'altro, lo scrivi esplicitamente nel tuo codice.
__init__metodo e forse anche cercare automaticamente le sottoclassi e decorarle.