Est-ce qu'il y en a ici qui savent comment construire un objet qui utilise l'héritage multiple ?
Voici un exemple de code qui fonctionne mais je ne suis pas sûr que l'implémentation soit correcte :
class A:
def __init__(self, a):
print("A ctor called!")
self.a_ = a
def printa(self):
print(self.a_)
class B:
def __init__(self, b):
print("B ctor called!")
self.b_ = b
def printb(self):
print(self.b_)
class C(A, B):
def __init__(self, a, b, c):
self.a_ = a
self.b_ = b
self.c_ = c
c = C(11, 22, 33)
c.printb()
Output : 22
Ici c réussit bien à appeler la méthode printb() de la classe parent B et affiche 22 comme prévu.
Mon problème est que la construction de la classe C n'appelle pas du tout la construction des classes A et B.
Est-ce que cela est normal ?
En principe pour initialiser les attributs a_ et b_ j'aurais aimé utiliser la fonction super() mais je ne sais pas comment elle fonctionne avec l'héritage multiple...
Est-ce qu'un pro saurait comment il faut faire ?
Merci d'avance !
- Edité par ThomasAirain 17 octobre 2023 à 19:36:51
Souvent la solution à ce genre de problème va être d'utiliser des arguments nommés uniquement dans les initialiseurs, afin de permettre d'y piocher ce que l'on veut.
Et chaque classe doit être consciente qu'il peut y avoir une classe au-dessus dans la hiérarchie et donc lui donner les arguments excédentaires. C'est un contrat établi entre les classes.
class A:
def __init__(self, *, a, **kwargs):
super().__init__(**kwargs)
print("A ctor called!")
self.a = a
def printa(self):
print(self.a)
class B:
def __init__(self, *, b, **kwargs):
super().__init__(**kwargs)
print("B ctor called!")
self.b = b
def printb(self):
print(self.b)
class C(A, B):
def __init__(self, *, c, **kwargs):
super().__init__(**kwargs)
print("C ctor called!")
self.c = c
def printc(self):
print(self.c)
obj = C(a=11, b=22, c=33)
obj.printa()
obj.printb()
obj.printc()
chaque classe doit être consciente qu'il peut y avoir une classe au-dessus dans la hiérarchie et donc lui donner les arguments excédentaires. C'est un contrat établi entre les classes.
D'où une préférence à un appel aux __init__ de chaque classe plutôt que d'utiliser super: plus facile d'imaginer ce qu'il va se passer en étant explicite qu'avec une méthode implicite.
Pas vraiment, c'est même plutôt limitant (ça contraint les constructions possibles à partir de ces classes de base).
Je préfère me reposer sur les mécanismes de Python que d'inventer mon propre ordre de résolution qui risque de casser à la moindre petite modification.
...Je préfère me reposer sur les mécanismes de Python que d'inventer mon propre ordre de résolution qui risque de casser à la moindre petite modification.
Appeler explicitement l'__init__ d'un parent est aussi un mécanisme de python. Passer par super a aussi ses limites.
Oui, on peut aussi choisir de construire les objets en appelant __new__ et se passer d'__init__, c'est là encore un mécanisme de Python.
Pourtant, il vaut mieux écrire ses classes de façon à correspondre au comportement standard (ordre de résolution des méthodes) plutôt que d'avoir à le tordre.
Oui, on peut aussi choisir de construire les objets en appelant __new__ et se passer d'__init__, c'est là encore un mécanisme de Python.
Pourtant, il vaut mieux écrire ses classes de façon à correspondre au comportement standard (ordre de résolution des méthodes) plutôt que d'avoir à le tordre.
On fait ce qu'on veut pour autant qu'on ait de bonnes raisons de le faire (et l'ignorance n'est pas une de ces raisons). On peut donc utiliser __new__ à la place de... si tant est qu'on soit capable de le justifier tout comme on peut se passer de super()...
Je sais qu'en Django on utilise souvent les "mixin" qui ont un intérêt mais dans la réalité, en tant que développeur, j'en ai très rarement eu le besoin, et quand je pensais l'avoir, il se trouvait que cela m'apportait des problèmes par la suite dans mes développements.
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard) La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
Construire un objet avec héritage multiple ?
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
entwanne — @entwanne — Un zeste de Python — La POO en Python — Notions de Python avancées — Les secrets d'un code pythonique
entwanne — @entwanne — Un zeste de Python — La POO en Python — Notions de Python avancées — Les secrets d'un code pythonique
entwanne — @entwanne — Un zeste de Python — La POO en Python — Notions de Python avancées — Les secrets d'un code pythonique
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)