Python: Wie erweitert man eine große Klasse mit minimalen Codezeilen?

8

Ursprüngliche Problembeschreibung

Das Problem tritt auf, wenn ich einen maschinellen Lernalgorithmus mit numpy implementiere. Ich möchte eine neue Klasse ludmo , die genauso funktioniert wie numpy.ndarray , aber mit ein paar weiteren Eigenschaften. Zum Beispiel mit einer neuen Eigenschaft ludmo.foo . Ich habe mehrere Methoden ausprobiert, aber keine ist zufriedenstellend.

1. Wrapper

Zuerst habe ich eine Wrapper-Klasse für numpy.ndarray , as

erstellt %Vor%

Aber wenn ich eine Funktion verwende (in scikit-learn , die ich nicht ändern kann), um eine Liste von np.ndarray instance zu bearbeiten, muss ich zuerst alle data -Felder jedes ludmo -Objekts extrahieren und sie in a sammeln Liste. Danach ist die Liste sortiert und ich habe die Korrespondenz zwischen den Objekten data und original ludmo verloren.

2. Vererbung

Dann habe ich versucht, ludmo zu einer Unterklasse von numpy.ndarray zu machen, wie

%Vor%

Aber ein anderes Problem tritt dann auf: Die gebräuchlichste Art ein numpy.ndarray Objekt zu erstellen ist numpy.array(some_list) , was ein numpy.ndarray Objekt zurückgibt, und ich muss es in ein ludmo Objekt konvertieren. Aber bis jetzt habe ich keinen guten Weg gefunden, dies zu tun; Wenn Sie einfach das Attribut __class__ ändern, wird ein Fehler ausgegeben.

Ich bin neu bei Python und numpy, also muss es einen eleganten Weg geben, den ich nicht kenne. Jeder Rat wird geschätzt.

Es ist besser, wenn jemand eine generische Lösung geben kann, die nicht nur für die Klasse numpy.ndarray , sondern auch für alle Arten von Klassen gilt.

    
xyguo 02.03.2015, 07:21
quelle

2 Antworten

2

Da Sie nach einer generischen Lösung fragen, können Sie hier eine generische Wrapper-Klasse verwenden: (aus Ссылка )

%Vor%

So funktioniert das:

wenn z.B. skicit würde ludmo.data python tatsächlich aufrufen %Code% Wenn ludmo nicht das Attribut 'data' hat, ruft Python auf ludmo.__getattribute__('data')

Durch Überschreiben der Funktion ludmo.__getattr__('data') , die diesen Aufruf abfängt, überprüfen Sie, ob Ihr ludmo das __getattr__ -Attribut hat (andernfalls könnten Sie sonst in Rekursion kommen), und senden Sie den Aufruf an Ihr internes Objekt. Sie sollten also jeden möglichen Aufruf an Ihr internes numpiges Objekt behandelt haben.

aktualisieren : Sie müssten auch data auf die gleiche Weise implementieren, oder Sie würden dies erhalten

%Vor%

und wahrscheinlich möchten Sie auch eine neue Metaklasse festlegen, die Aufrufe an magische Funktionen neuer Stilklassen abfängt (vollständige Klassen finden Sie unter Ссылка Für Informationen siehe Wie kann ich Abfangen von Pythons "magischen" Methoden in neuen Stilklassen? ) Dies ist jedoch nur erforderlich, wenn Sie weiterhin auf __setattr__ oder x.__name__ zugreifen und das magische Attribut von der umschlossenen Klasse und nicht von Ihrer Klasse erhalten möchten.

%Vor%     
Jens Timmerman 04.03.2015, 08:56
quelle
4

Als in den Dokumenten erläutert, können Sie Ihre eigenen Methoden zu np.ndarray hinzufügen. tun:

%Vor%

und dann Erstellen der Instanzen mit dem np.ndarray.view() Methode :

%Vor%

Und verwenden Sie die Methode __array_finalize__() , um neue Attribute zu definieren:

%Vor%     
Saullo Castro 07.03.2015 09:51
quelle