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% 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.
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.
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%Tags und Links python