wie die Argumente übergeben, die effizient (**kwargs in python)
Habe ich eine Klasse, die erbt von 2 anderen Klassen. Diese sind die Basis Klassen:
class FirstBase(object):
def __init__(self, detail_text=desc, backed_object=backed_object,
window=window, droppable_zone_obj=droppable_zone_obj,
bound_zone_obj=bound_zone_object,
on_drag_opacity=on_drag_opacity):
# bla bla bla
class SecondBase(object):
def __init__(self, size, texture, desc, backed_object, window):
# bla bla bla
- Und das ist das Kind:
class Child(FirstBase, SecondBase):
""" this contructor doesnt work
def __init__(self, **kwargs):
# PROBLEM HERE
#super(Child, self).__init__(**kwargs)
"""
#have to do it this TERRIBLE WAY
def __init__(self, size=(0,0), texture=None, desc="", backed_object=None,
window=None, droppable_zone_obj=[], bound_zone_object=[],
on_drag_opacity=1.0):
FirstBase.__init__(self, detail_text=desc, backed_object=backed_object,
window=window, droppable_zone_obj=droppable_zone_obj,
bound_zone_obj=bound_zone_object,
on_drag_opacity=on_drag_opacity)
SecondBase.__init__(self, size, texture, desc, backed_object, window)
Wollte ich es lösen, alles schön mit **kwargs
aber wenn ich die erste auskommentiert Konstruktor bekomme ich TypeError: __init__() got an unexpected keyword argument 'size'
.
Irgendwelche Ideen, wie ich es machen kann, die Arbeit mit **kwargs?
- Bei der ersten Lesung dieses (und nicht Massiv in die Tiefe ich zugeben), mein Erster Gedanke ist "gibt es wirklich zwei Basis-Klassen?" Es scheint viel zu viel überlappung zwischen den beiden; ie,
SecondBase
sieht aus wie es sein sollte ErbenFirstBase
re-Implementierung einiger Methoden und hinzufügen von anderen, was würden Sie dann machen es die einzige Basis fürChild
und vereinfachen Sie Ihre Hierarchie und OO-design - Ich brauche, um Sie zu beheben (einige code Bereinigung), aber Nein, Sie sind verschiedene Basen... ich kenn die Lösung für dieses problem
- Die derzeit akzeptierte Antwort von Diedrich ist ungenau, um den Umfang meiner Kenntnisse. Ich habe meine Antwort hier: stackoverflow.com/a/32135160/2801814
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dein problem ist, dass Sie nur versuchten, Sie zu verwenden
super
in die Kind-Klasse.Wenn Sie
super
in der Basis-Klassen zu, dann funktioniert das. Jeder Konstruktor wird "Essen" die keyword-Argumente, die es braucht, und geben Sie nicht bis zum nächsten Konstruktor. Wenn der Konstruktor fürobject
genannt wird, wenn es keine keyword-Argumente übrig, es wird eine Ausnahme ausgelöst.Wie Sie sehen können, es funktioniert, außer wenn Sie an eine falsche keyword-argument:
super()
im base-Klassen passt einfach die Reste inkwargs
bis zu denobject
Klasse und stürzt Sie. Dies ist auch eine schlechte Nutzung dersuper()
. Ich habe eine Antwort Beschreibung mehr.TypeError
auf unbekanntes Schlüsselwort-Argumente.object
. Alles, was Sie tun, ist die Wiederholung dieses Aufrufs, um Weg zu werfen, die Argumente in**kwargs
, die nicht zugewiesen wird.__init__()
Methode wird aufgerufen, ausChild
,FirstBase
,SecondBase
, und von der Zeit kommt es zuobject
gibt es keine keyword-Argumente Links. Nichts wird weggeworfen, jedes argument ist verbraucht genau eine Funktion, und jede zusätzliche Argumente werfen eineTypeError
. Vielleicht könnten Sie demonstrieren Ihren Ansatz mit ein paar Beispiel-code?super()
nicht von den Eltern. Denkst du, dasssuper(FirstBase, self).__init__(**kwargs)
Anrufeobject.__init__(self, **kwargs)
? Denn das ist nicht, was er tut.super()
und**kwargs
.Ich weiß nicht, wie diese Lösung, aber Sie können dies tun:
Weil
FirstBase.__init__
nicht diesize
argument. Sie können entweder fügen Sie diesize
argument oder fügen Sie**kwargs
zuFirstBase.__init__
.Probieren Sie etwas wie dieses.
einen möglichen hack (aber hacken ist schlecht, denken Sie daran), ist die Anrufung des inspect-Moduls zu erhalten, wird die Signatur der Funktion, die Sie verwenden:
Dies ist nicht ein code, den Sie verwenden sollten in der Produktion code. Wenn die Funktion weigert sich, einige Argumente, die es bedeutet, dass Sie können, erhalten Sie die Unterschrift Lesen Sie den code, und übergeben nur die benötigten Tasten. Das hack mit inspect ist weit weniger stabil und lesbar, so verwenden Sie nur, wenn Sie haben keine andere Möglichkeit!
Da haben Sie die Kontrolle über den code, der einfache Weg zu lassen, sich selbst einfach vorbeikommen **kwargs, wie Sie wollen, ist das hinzufügen einer **kwargs parameter der __init__ von beiden Basisklassen, etwa so:
Den Fehler Sie begegnet ist, weil Ihre Basis-Klassen nur hatte, benannte Parameter, daher, wenn Sie übergeben ein unbekannter name, der Türsteher sagt, du bist nicht auf meiner Liste. Durch das hinzufügen von **kwargs Parameter der __init__ - Funktionen des Basis-Klassen, Sie plötzlich zu ermöglichen, jede beliebige benannte Wert einfach in übergeben werden, das ist verständlich, weil, nachdem alle, **kwargs ist ein open-ended-catch all, nichts von dem Namen, so wie würden Sie wissen, was Sie ausschließen? Es einfach endet ein Wörterbuch der benannten Werte in den Augen der genannte code, der Sie verwendet oder nicht. Sie könnten vollständig zu ignorieren, **kwargs.
Die Antwort, die im moment des Schreibens ist allgemein akzeptiert, als die richtige, von Dietrich, verwirrt die wesentlichen Problem-es hat nichts zu tun mit super() an alle, und seiner Korrektur arbeitet, einfach, weil **kwargs wurden Hinzugefügt, und das öffnete die Tür für jeden beliebigen Namen.
Wenn Sie keine Kontrolle über den code haben, können Sie:
oder Sie können diese helper-meta-Funktion:
Diese anykwarg Helfer verbessert werden könnte, um zu überprüfen, ob ein parameter kwargs und, falls vorhanden, nicht entfernen Sie alle Werte aus der kwargs übergeben und überprüfen.getargspec oben verwendet, die diese Informationen zurückgibt. Beachten Sie, es ist okay, del von kwargs in anykwarg denn es ist nicht ein Verweis auf ein dictionary übergeben wird, ist es einem lokalen Wörterbuch, generiert aus den Parametern.
Sollten Sie nicht rufen Sie
super()
in der Basis-Klassen, wie in die akzeptierte Antwort von @Dietrich Epp. Alles, was Sie tun, ist vorbei, übrig gebliebene Argumente inkwargs
bis zu denobject
Basis-Klasse, wo Sie weggeworfen; das ist schlampig.Wenn Sie
super(ChildClass, self).__init__(foo, bar, **kwargs)
, die super-Klasse(N) vonChildClass
müssen damit rechnen, alle die Argumentefoo
,bar
, und**kwargs
. Also in deinem Fall, immer die FehlerTypeError: __init__() got an unexpected keyword argument 'size'
impliziert Ihre übergeordneten Klassen vonChild
entweder nichtsize
oder nicht**kwargs
in Ihrer__init__()
Methoden.Wenn Ihr
super()
Aufruf geht an jeden derFirstbase
undSecondbase
Ihre Konstruktoren versuchen und entpacken**kwargs
in Ihre keyword-Argumenten. Alles in**kwargs
braucht, um irgendwohin zu gehen. Alles übrig gebliebene (d.h. nicht durch ein Schlüsselwort-argument), wiesize
wird erhöhen Sie Ihr TypeError, es sei denn, es ist ein weiterer**kwargs
für die Reste, um zu gehen.object
Konstruktor keine Argumente akzeptiert, so dass keines der Argumente wird weggeworfen. Ich glaube, dass ich gezeigt, diese in die untere Hälfte meiner Antwort. Ich sehe nicht, was ist schlampig über die Methode, die ich vorgestellt: Sie können nur die keyword-Argumente, die ausdrücklich akzeptiert, indem Sie einen Konstruktor, andere keyword-Argumente, die Fehler auslösen.**kwargs
braucht, um irgendwohin zu gehen", d.h. alle Argumente zunächst in**kwargs
vom Kind zu werden, müssen in der übergeordneten Konstruktoren.**kwargs
verwendet wird, durch eine der übergeordneten Konstruktoren. Dieobject
Konstruktor ohne Argumente, so wirft es einen Fehler aus, wenn es irgendwelche Argumente übrig.