Wie werden alle Methoden einer enthaltenen Klasse in Python umgeleitet?

8

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.

    
Yariv 19.11.2012, 19:39
quelle

2 Antworten

16

Vorbehalte:

  • DataFrames haben viele Attribute. Wenn ein 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 .
  • Komponententests werden auch für __getitem__ benötigt.
  • Außerdem müssen Sie den Test __setattr__ und __setitem__ , __iter__ , __len__ usw. definieren und zusammenführen.
  • Beizen ist eine Form der Serialisierung. Wenn also 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) .

%Vor%

Hier ist ein zufälliger Code, um zu testen, ob - zumindest oberflächlich - Container korrekt an DataFrame s delegiert und Containers zurückgibt:

%Vor%     
unutbu 19.11.2012, 21:07
quelle
1

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%     
Waylon Walker 08.12.2016 13:12
quelle