Die Methoden __subclasscheck__
und __subclasshook__
werden verwendet, um zu bestimmen, ob eine Klasse als Unterklasse eines anderen betrachtet wird. Ihre Dokumentation ist jedoch selbst in fortgeschrittenen Python-Büchern sehr begrenzt. Wie sollen sie verwendet werden und was ist ihr Unterschied (höhere Priorität, Seite der Beziehung, auf die sie sich beziehen usw.)?
Beide Methoden können verwendet werden, um das Ergebnis der integrierten Funktion issubclass()
anzupassen.
__subclasscheck__
class.__subclasscheck__(self, subclass)
Gibt true zurück, wenn die Unterklasse als (direkte oder indirekte) Unterklasse der Klasse betrachtet werden soll. Wenn definiert, wird
issubclass(subclass, class)
implementiert.Beachten Sie, dass diese Methoden nach dem Typ (Metaklasse) einer Klasse gesucht werden. Sie können nicht als Klassenmethoden in der aktuellen Klasse definiert werden. Dies entspricht der Suche nach speziellen Methoden, die für Instanzen aufgerufen werden. Nur in diesem Fall ist die Instanz selbst eine Klasse.
Diese Methode ist die spezielle Methode, die für die Anpassung des issubclass
Checks verantwortlich ist. Wie die "Anmerkung" besagt, dass es auf der Metaklasse implementiert werden muss!
Diese Implementierung gibt False zurück, auch wenn Sie echte Unterklassen haben:
%Vor% Es gibt tatsächlich interessantere Verwendungen für __subclasscheck__
Implementierungen. Zum Beispiel:
Bei dieser Implementierung gibt jede Klasse, die __len__
und __iter__
definiert, True
in einem issubclass
check zurück:
In diesen Beispielen habe ich die Oberklassen __subclasscheck__
nicht aufgerufen und dadurch das normale Verhalten issubclass
deaktiviert (was durch type.__subclasscheck__
implementiert wird). Aber es ist wichtig zu wissen, dass Sie auch nur das erweitern normale Verhalten ändern können, anstatt es vollständig zu überschreiben:
__subclasshook__
__subclasshook__(subclass)
(Muss als Klassenmethode definiert sein.)
Überprüfen Sie, ob die Unterklasse als Unterklasse dieses ABCs betrachtet wird. Dies bedeutet, dass Sie das Verhalten von
issubclass
weiter anpassen können, ohne dass Sieregister()
für jede Klasse aufrufen müssen, die Sie als Unterklasse von ABC betrachten möchten. (Diese Klassenmethode wird von der Methode__subclasscheck__()
des ABC aufgerufen.)Diese Methode sollte
True
,False
oderNotImplemented
zurückgeben. Wenn sieTrue
zurückgibt, wird die Unterklasse als eine Unterklasse dieses ABC betrachtet. Wenn sieFalse
zurückgibt, wird die Unterklasse nicht als Unterklasse dieses ABC betrachtet, selbst wenn sie normalerweise eins wäre. Wenn esNotImplemented
zurückgibt, wird die Unterklassenprüfung mit dem üblichen Mechanismus fortgesetzt.
Das wichtigste hier ist, dass es in der Klasse als classmethod
definiert ist und von abc.ABC.__subclasscheck__
aufgerufen wird. Sie können es also nur verwenden, wenn Sie mit Klassen arbeiten, die eine ABCMeta
metaclass haben:
Dies wird nur in die __subclasshook__
der ersten gehen:
Beachten Sie, dass nachfolgende Aufrufe von issubclass
nicht mehr in __subclasshook__
übernommen werden, weil ABCMeta
das Ergebnis zwischenspeichert:
Beachten Sie, dass Sie in der Regel überprüfen, ob das erste Argument die Klasse selbst ist. Das soll verhindern, dass Unterklassen das __subclasshook__
erben, anstatt die normale Unterklassenbestimmung zu verwenden.
Zum Beispiel (aus dem Modul CPython collections.abc
):
Wenn Sie also überprüfen, ob etwas eine Unterklasse von Hashable
ist, wird die benutzerdefinierte __subclasshook__
-Implementierung verwendet, die von if cls is Hashable
geschützt wird. Wenn Sie jedoch eine tatsächliche Klasse haben, die die Hashable
-Schnittstelle implementiert, wollen Sie nicht, dass sie den __subclasshook__
-Mechanismus erbt, sondern den normalen Unterklassenmechanismus.
Zum Beispiel:
%Vor% Auch wenn int
implementiert __hash__
und __subclasshook__
prüft auf eine __hash__
Implementierung ist das Ergebnis in diesem Fall False
. Es gibt immer noch __subclasshook__
von Hashable
ein, aber es gibt sofort NotImplemented
zurück, das an ABCMeta
signalisiert, dass es mit der normalen Implementierung fortfahren soll. Wenn es nicht if cls is Hashable
hätte, würde issubclass(int, MyHashable)
True
zurückgeben!
__subclasscheck__
und wann __subclasshook__
verwenden? Es kommt wirklich darauf an. __subclasshook__
kann für die Klasse anstelle der Metaklasse implementiert werden, erfordert aber, dass Sie ABCMeta
(oder eine Unterklasse von ABCMeta
) als Metaklasse verwenden, da die Methode __subclasshook__
eigentlich nur eine Konvention ist, die von Pythons abc
eingeführt wurde. Modul.
Sie können immer __subclasscheck__
verwenden, aber es muss in der Metaklasse implementiert werden.
In der Praxis verwenden Sie __subclasshook__
, wenn Sie Schnittstellen implementieren (weil diese normalerweise abc
verwenden) und den Unterklassenmechanismus anpassen möchten. Und du benutzt __subclasscheck__
, wenn du deine eigenen Konventionen erfinden willst (wie abc
). In 99,99% der normalen (nicht spaßigen) Fälle benötigen Sie nur __subclasshook__
.
__subclasshook__
und __subclasscheck__
wird verwendet, um das Verhalten von issubclass
function anzupassen.
Viele weitere Informationen finden Sie im abc-Quellcode .
__subclasscheck__
wird nach dem Typ (Metaklasse) einer Klasse gesucht. Es sollte nicht für eine normale Klasse definiert werden.
__subclasshook__
prüft, ob die Unterklasse als Unterklasse eines ABC betrachtet wird. Dies bedeutet, dass Sie das Verhalten von issubclass
weiter anpassen können, ohne register () für jede Klasse aufrufen zu müssen, die Sie als Unterklasse von ABC betrachten möchten.
Dies bedeutet, dass Sie __subclasshook__
in Ihrer ABC-Klasse mit einer Bedingung definieren können und alle Klassen, die diese Bedingung erfüllen, werden als Unterklasse betrachtet.
Zum Beispiel:
%Vor%Tags und Links python python-3.x