Mehrfachvererbung in Python ist3 mit unterschiedlichen Signaturen
Habe ich drei Klassen: A
, B
und C
.
C
erbt von A
und B
(in dieser Reihenfolge). Die Konstruktor-Signaturen von A
und B
unterschiedlich sind. Wie kann ich rufen Sie die __init__
Methoden der übergeordneten Klassen?
Mein bemühen in code:
class A(object):
def __init__(self, a, b):
super(A, self).__init__()
print('Init {} with arguments {}'.format(self.__class__.__name__, (a, b)))
class B(object):
def __init__(self, q):
super(B, self).__init__()
print('Init {} with arguments {}'.format(self.__class__.__name__, (q)))
class C(A, B):
def __init__(self):
super(A, self).__init__(1, 2)
super(B, self).__init__(3)
c = C()
ergibt den Fehler:
Traceback (most recent call last):
File "test.py", line 16, in <module>
c = C()
File "test.py", line 13, in __init__
super(A, self).__init__(1, 2)
TypeError: __init__() takes 2 positional arguments but 3 were given
Fand ich diese Ressource die erklärt, multiple Vererbung mit unterschiedlichen Argumenten, aber Sie schlagen die Verwendung *args
und **kwargs
für alle argument. Ich halte dies für sehr hässlich, da kann ich nicht sehen, aus dem Konstruktor-Aufruf in der Kind-Klasse, welche Parameter ich übergeben, um die übergeordneten Klassen.
- Sie sind mit
super
falsch, das sollte genauso seinsuper(C, self).__init__
imC.__init__
. Als Sie haben unterschiedliche Signaturen, haben Sie keine Wahl, sondern handle willkürlich*args, **kwargs
wenn Sie verwenden möchtensuper
. super()
ist, wenn Sie aus der Verwendung von Mixins in Verbindung. Nicht verwenden, wenn Sie verschiedene Signaturen.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Tun nicht verwenden
super(baseclass, ...)
es sei denn, Sie wissen, was Sie tun. Das erste argumentsuper()
sagt, was er Klasse überspringen bei der Suche nach der nächsten Methode zu verwenden. E. g.super(A, ...)
der Blick auf das MRO, findenA
, dann starten Sie suchen für__init__
auf die nächsten baseclass, nichtA
selbst. FürC
die MRO ist(C, A, B, object)
, sosuper(A, self).__init__
findenB.__init__
.Für diese Fälle, die Sie nicht verwenden möchten, Genossenschaft erbschaft, sondern direkt auf
A.__init__
undB.__init__
statt.super()
sollte nur verwendet werden, wenn die Methoden, die Sie anrufen, haben die gleiche Signatur oder schlucken nicht unterstützten Argumente mit*args
und**vargs
. In diesem Fall wird nur die einesuper(C, self).__init__()
Anruf wäre nötig, und die nächste Klasse im MRO-Bestellung aufpassen würde Verkettung auf den Anruf.Setzen es anders: wenn Sie
super()
können Sie nicht wissen, welche Klasse wird weiter in die Instandhaltung, so dass die Klasse besser, die Unterstützung der Argumente, die übergeben werden. Wenn das nicht der Fall ist, darf nicht Verwendungsuper()
.Aufruf der Basis
__init__
Methoden direkt:Mit kooperativen
super()
:__init__
ist sehr Konter-intuitiv...Was auch immer, deine Antwort ist einfach AUSGEZEICHNET, ich danke Ihnen so sehr!super()
versucht zu lösen: beim Aufruf der next - Methode in der Reihenfolge, in einer komplexen Hierarchie mit Diamant-Muster der Vererbung (Basisklasse verwendet, die von mehreren Unterklassen). In solchen Fällen expliziteBaseClass.__init__
Anrufe wird fehleranfällig und Sie am Ende mit mehreren anrufen zuSharedBaseClass.__init__
. Durch die Verwendung der MRO-stattdessen haben Sie einen garantierten bestellen, aber die Bestellung ist dynamic basiert auf Vererbung. Dies bedeutet, dass Sie, sollten Sie nicht Sorge darüber, was die nächste Klasse ist, so stellen Sie sicher, dass alle von Ihnen akzeptieren können, dass call.