Riesige Konstruktoren bändigen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Hi Community,

ich arbeite gerade an einem python projekt, wo es heißt mit Objekten zu arbeiten, die viele Daten beherbergen :)

Nun stellt sich die Frage wie geht ihr mit riesigen Konstruktoren um?
Bsp.:

Code: Alles auswählen

class A(object):
    def __init__(self, a, b, c, d, f = None, g = None, weiter = None, nochweiter = None, nochsehrvielweiter = None, unendlich = None):
        pass
Habt ihr dafür ein "Rezept" wie man daraus ansehnlicheren Code schreibt? Was macht ihr wenn ihr das 80 Zeilen Limit einhalten wollt?

Vor allem, was macht ihr wenn sich solche Konstruktoren über mehrere Klassen hinweg häufen?

Eine Möglichkeit wäre eine Vererbung festzustellen, aber nur da wo sie auch wirklich Sinn macht, und entsprechend die Konstruktoren anpassen:

Code: Alles auswählen

class A(object):
    def __init__(self, a, b, c, d, f = None, g = None, weiter = None, nochweiter = None, nochsehrvielweiter = None, unendlich = None):
        print a, b, c, d
        pass


class B(A):
    def __init__(self, *args, **kwargs):        
        super(*args, **kwargs)
        pass
        
        
class C(A):
    def __init__(self, *args, **kwargs):
        super(*args, **kwargs)
        pass


class D(A):
    def __init__(self, *args, **kwargs):
        super(*args, **kwargs)
        pass
Leider funktioniert das obige Beispiel noch nicht so ganz. Was mache ich falsch?

Leider wird es dadurch, sofern das Beispiel mal funktioniert, auch nicht wirklich übersichtlicher, da man immer bei A nachschauen muss, was denn überhaupt von B oder C verlangt wird.

Wie ihr seht befinde ich mich in einem Dilemma :)

Grüße,
anogayales
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

Code: Alles auswählen

class A(object):
    def __init__(self, **kwargs):
        self.a = kwargs.get('a', None)
        self.b = kwargs.get('b', None)
        ...
Bottle: Micro Web Framework + Development Blog
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Nimm sie als `**kwargs` an, was ja letztlich ein Dictionary ergibt. Innerhalb deiner `__init__`-Methode bröselst du die Dinger auseinander und in den Docstring schreibst du, welche Argumente erwartet werden. Sowas hab ich schon desöfteren gesehen.

@Defnull: Das `None` kann man sich sparen, da es standardmäßig als Fallback-Wert zurückgegeben wird.
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Aslo ganz verstanden habe ich das noch nicht. Die Rolle die A bei der Sache spielt ist mir klar und einleuchtend.

Aber sieht es mit den Subklassen aus?
Falls ich B so belasse wie oben im Beispiel kriege ich die Fehlermeldung:

Code: Alles auswählen

TypeError: super does not take keyword arguments
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Innerhalb von Klammern kannst du einfach Zeilenumbrüche machen. Ich persönlich bevorzuge dass im Gegensatz zu Defnulls Variante weil so die Signatur der Funktion nicht an Bedeutung verliert.

Abgesehen davon nutzt du super() falsch, schau dir nochmal die Dokumentation dazu an oder besser noch verwende es gar nicht erst.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Du bekommst den Fehler, weil super nicht das tut, was du denkst das es tut. Benutze besser

Code: Alles auswählen

A.__init__(self, *args, **kwargs)
Das Leben ist wie ein Tennisball.
BlackJack

@anogayales: Neben den bisher genannten Tipps, kann man auch mal schauen ob sich Argumente sinnvoll zu eigenen Objekten zusammenfassen lassen.
Antworten