Seite 1 von 1

Riesige Konstruktoren bändigen

Verfasst: Freitag 28. Mai 2010, 13:47
von anogayales
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

Re: Riesige Konstruktoren bändigen

Verfasst: Freitag 28. Mai 2010, 13:50
von Defnull

Code: Alles auswählen

class A(object):
    def __init__(self, **kwargs):
        self.a = kwargs.get('a', None)
        self.b = kwargs.get('b', None)
        ...

Re: Riesige Konstruktoren bändigen

Verfasst: Freitag 28. Mai 2010, 13:51
von snafu
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.

Re: Riesige Konstruktoren bändigen

Verfasst: Freitag 28. Mai 2010, 14:01
von anogayales
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

Re: Riesige Konstruktoren bändigen

Verfasst: Freitag 28. Mai 2010, 14:04
von DasIch
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.

Re: Riesige Konstruktoren bändigen

Verfasst: Freitag 28. Mai 2010, 14:05
von EyDu
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)

Re: Riesige Konstruktoren bändigen

Verfasst: Freitag 28. Mai 2010, 15:37
von BlackJack
@anogayales: Neben den bisher genannten Tipps, kann man auch mal schauen ob sich Argumente sinnvoll zu eigenen Objekten zusammenfassen lassen.