Java et C ++ exigent qu'un constructeur de classe de base soit appelé en raison de la disposition de la mémoire.
Si vous avez une classe BaseClass
avec un membre field1
et que vous créez une nouvelle classe SubClass
qui ajoute un membre field2
, une instance de SubClass
contient un espace pour field1
et field2
. Vous avez besoin d'un constructeur de BaseClass
pour remplir field1
, sauf si vous avez besoin que toutes les classes héritées répètent BaseClass
l'initialisation de leur propre constructeur. Et si field1
c'est privé, alors les classes héritées ne peuvent pas s'initialiser field1
.
Python n'est pas Java ou C ++. Toutes les instances de toutes les classes définies par l'utilisateur ont la même «forme». Ce sont essentiellement des dictionnaires dans lesquels des attributs peuvent être insérés. Avant qu'une initialisation n'ait été effectuée, toutes les instances de toutes les classes définies par l'utilisateur sont presque exactement les mêmes ; ce ne sont que des endroits pour stocker des attributs qui n'en stockent pas encore.
Il est donc parfaitement logique pour une sous-classe Python de ne pas appeler son constructeur de classe de base. Il pourrait simplement ajouter les attributs lui-même s'il le voulait. Il n'y a pas d'espace réservé pour un nombre donné de champs pour chaque classe dans la hiérarchie, et il n'y a aucune différence entre un attribut ajouté par code à partir d'une BaseClass
méthode et un attribut ajouté par code à partir d'une SubClass
méthode.
Si, comme cela est courant, vous SubClass
voulez vraiment que tous BaseClass
les invariants de s soient configurés avant de procéder à sa propre personnalisation, alors oui, vous pouvez simplement appeler BaseClass.__init__()
(ou utiliser super
, mais c'est compliqué et a parfois ses propres problèmes). Mais vous n'êtes pas obligé. Et vous pouvez le faire avant, ou après, ou avec différents arguments. Enfer, si vous le vouliez, vous pourriez appeler le BaseClass.__init__
d'une autre méthode que __init__
; peut-être que vous avez une initialisation paresseuse bizarre en cours.
Python atteint cette flexibilité en gardant les choses simples. Vous initialisez les objets en écrivant une __init__
méthode qui définit les attributs sur self
. C'est tout. Elle se comporte exactement comme une méthode, car c'est exactement une méthode. Il n'y a pas d'autres règles étranges et peu intuitives sur les choses à faire en premier, ou les choses qui se produiront automatiquement si vous ne faites pas d'autres choses. Le seul but qu'il doit servir est d'être un hook à exécuter pendant l'initialisation de l'objet pour définir les valeurs d'attribut initiales, et c'est exactement ce qu'il fait. Si vous voulez qu'il fasse autre chose, vous l'écrivez explicitement dans votre code.
__init__
méthode, et peut-être même rechercher automatiquement des sous-classes et les décorer.