Wie implementiert man das Zusammensetzungsmuster? Ich habe eine Klasse Container
, die ein Attribut-Objekt Contained
hat. Ich möchte den Zugriff auf alle Methoden von Contained
class von Container
umleiten / erlauben, indem ich einfach my_container.some_contained_method()
aufruft. Mache ich das Richtige richtig?
Ich benutze etwas wie:
%Vor%Hintergrund:
Ich versuche eine Klasse ( Indicator
) zu erstellen, die zur Funktionalität einer vorhandenen Klasse ( pandas.DataFrame
) beiträgt. Indicator
hat alle Methoden von DataFrame
. Ich könnte Vererbung verwenden, aber ich verfolge den Ratschlag "favor Komposition über Vererbung " (siehe z. B. die Antworten in: python: erben oder kompilieren ). Ein Grund, nicht zu erben, liegt darin, dass die Basisklasse nicht serialisierbar ist und ich serialisieren muss.
Ich habe dies gefunden, bin mir aber nicht sicher, ob es meinen Bedürfnissen entspricht.
Vorbehalte:
DataFrame
-Attribut eine Zahl ist, möchten Sie wahrscheinlich nur diese Zahl zurückgeben. Wenn das Attribut DataFrame
jedoch DataFrame
ist, möchten Sie wahrscheinlich Container
zurückgeben. Was sollten wir tun, wenn das Attribut DataFrame
ein Series
oder ein Deskriptor ist? Um Container.__getattr__
korrekt zu implementieren, bist du wirklich
muss für jedes Attribut Einheitentests schreiben . __getitem__
benötigt. __setattr__
und __setitem__
, __iter__
, __len__
usw. definieren und zusammenführen. DataFrames
einfügbar ist, bin ich nicht sicher, wie Container
s wirklich bei der Serialisierung hilft. Einige Kommentare:
__getattr__
wird nur aufgerufen, wenn das Attribut nicht in self.__dict__
steht. Sie brauchen also if item in self.__dict__
in Ihrem __getattr__
nicht.
self.contained.__getattr__(item)
ruft self.contained
auf
__getattr__
Methode direkt. Das ist normalerweise nicht das, was du willst
tun, weil es die gesamte Python-Attributsuche umgeht
Mechanismus. Zum Beispiel ignoriert es die Möglichkeit, dass das Attribut
könnte in self.contained.__dict__
oder in __dict__
von einem sein
die Basis von self.contained.__class__
oder wenn item
sich auf a bezieht
Beschreibung. Verwenden Sie stattdessen getattr(self.contained, item)
.
Hier ist ein zufälliger Code, um zu testen, ob - zumindest oberflächlich - Container
korrekt an DataFrame
s delegiert und Containers
zurückgibt:
Ich fand die Antwort von unbutbu sehr nützlich für meine eigene Anwendung, ich stieß auf Probleme, die es richtig in einem jupyter Notizbuch zeigten. Ich habe festgestellt, dass das Hinzufügen der folgenden Methoden zu der Klasse das Problem behoben hat.
%Vor%Tags und Links python inheritance pandas composition