Wie verifiziere Duck-typed Interfaces in Python?

8
%Vor%

Im obigen Beispiel wird issubclass(TypeType*, ITestType) für 2 Wahr und für 1 und 3 falsch zurückgeben.

Gibt es eine alternative Möglichkeit, issubclass zu verwenden, oder eine alternative Methode zum Testen der Schnittstelle, die es 1 und 2 erlaubt, zu bestehen, aber 3 abzulehnen?

Es wäre sehr hilfreich für mich, die Duck-Typisierung anstelle von explizit bindenden Klassen für abstrakte Typen zu verwenden, aber auch die Objektüberprüfung zu ermöglichen, wenn duck-typed-Objekte bestimmte Schnittstellen passieren.

Ja, ich bin mir bewusst, dass Python-Leute keine Schnittstellen mögen, und die Standardmethodik lautet "finde sie, wenn sie fehlschlägt und alles in Ausnahmen umwandelt", aber auch völlig irrelevant für meine Frage. Nein, ich kann in diesem Projekt einfach keine Interfaces verwenden.

bearbeiten:

Perfekt! Für jeden, der diese Frage findet, hier ein Beispiel für die Verwendung von subclasshook:

%Vor%     
Doug 10.02.2012, 06:38
quelle

3 Antworten

9

Sehen Sie sich das Modul ABC an. Sie können eine abstrakte Basisklasse definieren, die eine __subclasshook__ -Methode bereitstellt, die definiert, ob eine bestimmte Klasse "eine Unterklasse" der abstrakten Basisklasse ist, basierend auf beliebigen Kriterien - wie "es hat Methoden X, Y und Z" oder Wasauchimmer. Dann können Sie issubclass() oder isinstance() verwenden, um Interfaces für Klassen und Instanzen zu erkennen.

    
kindall 10.02.2012, 06:47
quelle
2

Dies ist ein paar Jahre zu spät, aber hier ist die Art, wie ich es gemacht habe:

%Vor%

Wenn C eine versuchte Klasse von MetaClass ist, dann ist C.__abstractmethods__ nur dann leer, wenn C alle abstrakten Methoden implementiert.

Siehe hier für die Details: Ссылка (es ist unter "Implementierung", aber eine Suche nach __abstractmethods__ sollte Sie zum richtigen Absatz bringen)

Wo hat das für mich funktioniert:

Ich kann MetaClass erstellen. Ich kann dann BaseClass und MetaClass ableiten, um SubClass zu erstellen, das zusätzliche Funktionalität benötigt. Aber ich muss eine Instanz von BaseClass nach unten auf SubClass umwandeln, indem ich das __cls__ Attribut ändere, da ich BaseClass nicht besitze, aber ich bekomme Instanzen davon, die ich ablegen möchte.

Wenn ich jedoch SubClass falsch implementiere, kann ich immer noch ablegen, wenn ich nicht die obige __subclasshook__ benutze und nur eine Unterklassenprüfung hinzufüge, wenn ich den Cast-Prozess mache (was ich sowieso tun sollte, da ich nur möchte) Versuchen Sie, eine Elternklasse zu deaktivieren). Wenn jemand darum bittet, kann ich dafür ein MWE bereitstellen.

ETA: Hier ist ein MWE. Ich denke, was ich vorhin vorgeschlagen habe, war falsch, so scheint das Folgende zu tun, was ich vorhatte.

Das Ziel besteht darin, ein Objekt BaseClass in SubClass und zurück konvertieren zu können. Von SubClass bis BaseClass ist einfach. Aber von BaseClass bis SubClass nicht so viel. Normalerweise wird das Attribut __class__ aktualisiert, aber es bleibt eine Öffnung, wenn SubClass nicht wirklich eine Unterklasse ist oder von einer abstrakten Metaklasse abgeleitet ist, aber nicht richtig implementiert ist.

Unten wird die Konvertierung in der Methode convert durchgeführt, die BaseMetaClass implementiert. In dieser Logik überprüfe ich jedoch zwei Dinge. Um in die Unterklasse zu konvertieren, überprüfe ich, ob es tatsächlich eine Unterklasse ist. Zweitens überprüfe ich das Attribut __abstractmethods__ , um zu sehen, ob es leer ist. Wenn ja, dann ist es auch eine korrekt implementierte Metaklasse. Fehler führt zu einem TypeError. Andernfalls wird das Objekt konvertiert.

%Vor%     
Alex 22.06.2015 18:34
quelle
1

Hier ist eine Alternative, die auch in der Praxis sehr gut funktioniert, ohne das mühsame Überprüfen des gesamten Wörterbuchs bei jeder Klasseninstanz-Erstellung.

(py2 und py3 kompatibel)

Verwendung:

%Vor%

Sie können auch offensichtliche Dinge wie @implements (Stream, Folder, Bar) tun, wenn sie alle die gleichen Methoden benötigen, was praktisch praktischer ist als die Vererbung.

Code:

%Vor%     
Doug 06.09.2013 06:46
quelle

Tags und Links