abc — Abstrakte Basisklassen¶
Quellcode: Lib/abc.py
Dieses Modul stellt die Infrastruktur zur Definition von abstrakten Basisklassen (ABCs) in Python bereit, wie in PEP 3119 beschrieben; siehe die PEP für die Gründe, warum dies zu Python hinzugefügt wurde. (Siehe auch PEP 3141 und das Modul numbers bezüglich einer Typenhierarchie für Zahlen basierend auf ABCs.)
Das Modul collections enthält einige konkrete Klassen, die von ABCs abgeleitet sind; diese können natürlich weiter abgeleitet werden. Darüber hinaus enthält das Untermodul collections.abc einige ABCs, die verwendet werden können, um zu testen, ob eine Klasse oder Instanz eine bestimmte Schnittstelle bereitstellt, z. B. ob sie hashable ist oder ob sie eine mapping ist.
Dieses Modul stellt die Metaklasse ABCMeta zur Definition von ABCs und eine Hilfsklasse ABC zur alternativen Definition von ABCs durch Vererbung bereit
- class abc.ABC¶
Eine Hilfsklasse, die
ABCMetaals ihre Metaklasse hat. Mit dieser Klasse kann eine abstrakte Basisklasse einfach durch Ableiten vonABCerstellt werden, wodurch die manchmal verwirrende Verwendung von Metaklassen vermieden wird, zum Beispielfrom abc import ABC class MyABC(ABC): pass
Beachten Sie, dass der Typ von
ABCimmer nochABCMetaist. Daher erfordert die Vererbung vonABCdie üblichen Vorsichtsmaßnahmen bezüglich der Verwendung von Metaklassen, da Mehrfachvererbung zu Metaklassenkonflikten führen kann. Man kann auch eine abstrakte Basisklasse definieren, indem man das Schlüsselwort `metaclass` übergibt undABCMetadirekt verwendet, zum Beispielfrom abc import ABCMeta class MyABC(metaclass=ABCMeta): pass
Hinzugefügt in Version 3.4.
- class abc.ABCMeta¶
Metaklasse zur Definition von Abstrakten Basisklassen (ABCs).
Verwenden Sie diese Metaklasse, um eine ABC zu erstellen. Eine ABC kann direkt unterklassifiziert werden und fungiert dann als Mix-in-Klasse. Sie können auch nicht verwandte konkrete Klassen (sogar eingebaute Klassen) und nicht verwandte ABCs als "virtuelle Unterklassen" registrieren – diese und ihre Nachkommen werden von der integrierten Funktion
issubclass()als Unterklassen der registrierenden ABC betrachtet, aber die registrierende ABC wird nicht in ihrer MRO (Method Resolution Order) angezeigt, noch werden von der registrierenden ABC definierte Methodenimplementierungen aufrufbar sein (nicht einmal übersuper()). [1]Klassen, die mit einer Metaklasse von
ABCMetaerstellt wurden, haben die folgende Methode- register(subclass)¶
Registriert subclass als "virtuelle Unterklasse" dieser ABC. Zum Beispiel
from abc import ABC class MyABC(ABC): pass MyABC.register(tuple) assert issubclass(tuple, MyABC) assert isinstance((), MyABC)
Geändert in Version 3.3: Gibt die registrierte Unterklasse zurück, um sie als Klassen-Decorator verwenden zu können.
Geändert in Version 3.4: Um Aufrufe von
register()zu erkennen, können Sie die Funktionget_cache_token()verwenden.
Sie können diese Methode auch in einer abstrakten Basisklasse überschreiben
- __subclasshook__(subclass)¶
(Muss als Klassenmethode definiert werden.)
Prüft, ob subclass als Unterklasse dieser ABC betrachtet wird. Das bedeutet, dass Sie das Verhalten von
issubclass()weiter anpassen können, ohneregister()für jede Klasse aufrufen zu müssen, die Sie als Unterklasse der ABC betrachten möchten. (Diese Klassenmethode wird von der Methode__subclasscheck__()der ABC aufgerufen.)Diese Methode sollte
True,FalseoderNotImplementedzurückgeben. Wenn sieTruezurückgibt, wird subclass als Unterklasse dieser ABC betrachtet. Wenn sieFalsezurückgibt, wird subclass nicht als Unterklasse dieser ABC betrachtet, auch wenn sie es normalerweise wäre. Wenn sieNotImplementedzurückgibt, wird die Unterklassenprüfung mit dem üblichen Mechanismus fortgesetzt.
Für eine Demonstration dieser Konzepte siehe dieses Beispiel für eine ABC-Definition
class Foo: def __getitem__(self, index): ... def __len__(self): ... def get_iterator(self): return iter(self) class MyIterable(ABC): @abstractmethod def __iter__(self): while False: yield None def get_iterator(self): return self.__iter__() @classmethod def __subclasshook__(cls, C): if cls is MyIterable: if any("__iter__" in B.__dict__ for B in C.__mro__): return True return NotImplemented MyIterable.register(Foo)
Die ABC
MyIterabledefiniert die Standard-Iterable-Methode,__iter__(), als abstrakte Methode. Die hier gegebene Implementierung kann immer noch von Unterklassen aufgerufen werden. Die Methodeget_iterator()ist ebenfalls Teil der abstrakten BasisklasseMyIterable, muss aber in nicht-abstrakten abgeleiteten Klassen nicht überschrieben werden.Die Klassenmethode
__subclasshook__(), die hier definiert ist, besagt, dass jede Klasse, die eine Methode__iter__()in ihrem__dict__hat (oder in dem einer ihrer Basisklassen, zugänglich über die Liste__mro__), ebenfalls alsMyIterablebetrachtet wird.Schließlich macht die letzte Zeile
Foozu einer virtuellen Unterklasse vonMyIterable, auch wenn sie keine Methode__iter__()definiert (sie verwendet das alte Iterable-Protokoll, das auf Basis von__len__()und__getitem__()definiert ist). Beachten Sie, dassget_iteratordadurch nicht als Methode vonFooverfügbar wird, daher wird sie separat bereitgestellt.
Das Modul abc stellt auch den folgenden Decorator bereit
- @abc.abstractmethod¶
Ein Decorator, der abstrakte Methoden kennzeichnet.
Die Verwendung dieses Decorators erfordert, dass die Metaklasse der Klasse
ABCMetaist oder von ihr abgeleitet ist. Eine Klasse, die eine vonABCMetaabgeleitete Metaklasse hat, kann nicht instanziiert werden, es sei denn, alle ihre abstrakten Methoden und Eigenschaften werden überschrieben. Die abstrakten Methoden können über beliebige normale 'super'-Aufrufmechanismen aufgerufen werden.abstractmethod()kann verwendet werden, um abstrakte Methoden für Eigenschaften und Deskriptoren zu deklarieren.Das dynamische Hinzufügen abstrakter Methoden zu einer Klasse oder der Versuch, den Abstraktionsstatus einer Methode oder Klasse nach ihrer Erstellung zu ändern, wird nur mit der Funktion
update_abstractmethods()unterstützt.abstractmethod()beeinflusst nur Unterklassen, die über reguläre Vererbung abgeleitet wurden; "virtuelle Unterklassen", die mit derregister()-Methode der ABC registriert wurden, sind nicht betroffen.Wenn
abstractmethod()in Kombination mit anderen Methoden-Deskriptoren verwendet wird, sollte es als innerster Decorator angewendet werden, wie in den folgenden Anwendungsbeispielen gezeigtclass C(ABC): @abstractmethod def my_abstract_method(self, arg1): ... @classmethod @abstractmethod def my_abstract_classmethod(cls, arg2): ... @staticmethod @abstractmethod def my_abstract_staticmethod(arg3): ... @property @abstractmethod def my_abstract_property(self): ... @my_abstract_property.setter @abstractmethod def my_abstract_property(self, val): ... @abstractmethod def _get_x(self): ... @abstractmethod def _set_x(self, val): ... x = property(_get_x, _set_x)
Um korrekt mit der abstrakten Basisklassen-Mechanik zu interagieren, muss der Deskriptor sich selbst als abstrakt identifizieren, indem er
__isabstractmethod__verwendet. Im Allgemeinen sollte dieses AttributTruesein, wenn eine der Methoden, die zur Zusammensetzung des Deskriptors verwendet werden, abstrakt ist. Zum Beispiel führt die eingebautepropertyvon Python das Äquivalent vonclass Descriptor: ... @property def __isabstractmethod__(self): return any(getattr(f, '__isabstractmethod__', False) for f in (self._fget, self._fset, self._fdel))
Hinweis
Im Gegensatz zu Java-abstrakten Methoden können diese abstrakten Methoden eine Implementierung haben. Diese Implementierung kann über den
super()-Mechanismus von der Klasse aufgerufen werden, die sie überschreibt. Dies könnte als Endpunkt für einen Super-Aufruf in einem Framework nützlich sein, das kooperative Mehrfachvererbung verwendet.
Das Modul abc unterstützt auch die folgenden Legacy-Decoratoren
- @abc.abstractclassmethod¶
Hinzugefügt in Version 3.2.
Veraltet seit Version 3.3: Es ist jetzt möglich,
classmethodmitabstractmethod()zu verwenden, was diesen Decorator überflüssig macht.Eine Unterklasse der eingebauten
classmethod(), die eine abstrakte Klassenmethode kennzeichnet. Ansonsten ist sie ähnlich wieabstractmethod().Dieser Sonderfall ist veraltet, da der Decorator
classmethod()nun korrekt als abstrakt identifiziert wird, wenn er auf eine abstrakte Methode angewendet wird.class C(ABC): @classmethod @abstractmethod def my_abstract_classmethod(cls, arg): ...
- @abc.abstractstaticmethod¶
Hinzugefügt in Version 3.2.
Veraltet seit Version 3.3: Es ist jetzt möglich,
staticmethodmitabstractmethod()zu verwenden, was diesen Decorator überflüssig macht.Eine Unterklasse der eingebauten
staticmethod(), die eine abstrakte statische Methode kennzeichnet. Ansonsten ist sie ähnlich wieabstractmethod().Dieser Sonderfall ist veraltet, da der Decorator
staticmethod()nun korrekt als abstrakt identifiziert wird, wenn er auf eine abstrakte Methode angewendet wird.class C(ABC): @staticmethod @abstractmethod def my_abstract_staticmethod(arg): ...
- @abc.abstractproperty¶
Veraltet seit Version 3.3: Es ist jetzt möglich,
property,property.getter(),property.setter()undproperty.deleter()mitabstractmethod()zu verwenden, was diesen Decorator überflüssig macht.Eine Unterklasse der eingebauten
property(), die eine abstrakte Eigenschaft kennzeichnet.Dieser Sonderfall ist veraltet, da der Decorator
property()nun korrekt als abstrakt identifiziert wird, wenn er auf eine abstrakte Methode angewendet wird.class C(ABC): @property @abstractmethod def my_abstract_property(self): ...
Das obige Beispiel definiert eine schreibgeschützte Eigenschaft; Sie können auch eine les- und schreibbare abstrakte Eigenschaft definieren, indem Sie eine oder mehrere der zugrunde liegenden Methoden entsprechend als abstrakt kennzeichnen.
class C(ABC): @property def x(self): ... @x.setter @abstractmethod def x(self, val): ...
Wenn nur einige Komponenten abstrakt sind, müssen nur diese Komponenten aktualisiert werden, um in einer Unterklasse eine konkrete Eigenschaft zu erstellen.
class D(C): @C.x.setter def x(self, val): ...
Das Modul abc unterstützt auch die folgenden Funktionen
- abc.get_cache_token()¶
Gibt das aktuelle Token des abstrakten Basisklassen-Caches zurück.
Das Token ist ein opakes Objekt (das Gleichheitstests unterstützt) und identifiziert die aktuelle Version des abstrakten Basisklassen-Caches für virtuelle Unterklassen. Das Token ändert sich bei jedem Aufruf von
ABCMeta.register()auf einer beliebigen ABC.Hinzugefügt in Version 3.4.
- abc.update_abstractmethods(cls)¶
Eine Funktion zur Neuberechnung des Abstraktionsstatus einer abstrakten Klasse. Diese Funktion sollte aufgerufen werden, wenn die abstrakten Methoden einer Klasse nach ihrer Erstellung implementiert oder geändert wurden. Normalerweise sollte diese Funktion innerhalb eines Klassen-Decorators aufgerufen werden.
Gibt cls zurück, um sie als Klassen-Decorator verwenden zu können.
Wenn cls keine Instanz von
ABCMetaist, tut die Funktion nichts.Hinweis
Diese Funktion geht davon aus, dass die Oberklassen von cls bereits aktualisiert sind. Sie aktualisiert keine Unterklassen.
Hinzugefügt in Version 3.10.
Fußnoten