class abc.ABCMeta
Metaclass for defining Abstract Base Classes (ABCs).
Use this metaclass to create an ABC. An ABC can be subclassed directly, and then acts as a mix-in class. You can also register unrelated concrete classes (even built-in classes) and unrelated ABCs as “virtual subclasses” – these and their descendants will be considered subclasses of the registering ABC by the built-in issubclass()
function, but the registering ABC won’t show up in their MRO (Method Resolution Order) nor will method implementations defined by the registering ABC be callable (not even via super()
). [1]
Classes created with a metaclass of ABCMeta
have the following method:
-
register(subclass)
-
Register subclass as a “virtual subclass” of this ABC. For example:
from abc import ABCMeta class MyABC(metaclass=ABCMeta): pass MyABC.register(tuple) assert issubclass(tuple, MyABC) assert isinstance((), MyABC)
Changed in version 3.3: Returns the registered subclass, to allow usage as a class decorator.
Changed in version 3.4: To detect calls to
register()
, you can use theget_cache_token()
function.
You can also override this method in an abstract base class:
-
__subclasshook__(subclass)
-
(Must be defined as a class method.)
Check whether subclass is considered a subclass of this ABC. This means that you can customize the behavior of
issubclass
further without the need to callregister()
on every class you want to consider a subclass of the ABC. (This class method is called from the__subclasscheck__()
method of the ABC.)This method should return
True
,False
orNotImplemented
. If it returnsTrue
, the subclass is considered a subclass of this ABC. If it returnsFalse
, the subclass is not considered a subclass of this ABC, even if it would normally be one. If it returnsNotImplemented
, the subclass check is continued with the usual mechanism.
For a demonstration of these concepts, look at this example ABC definition:
class Foo: def __getitem__(self, index): ... def __len__(self): ... def get_iterator(self): return iter(self) class MyIterable(metaclass=ABCMeta): @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)
The ABC MyIterable
defines the standard iterable method, __iter__()
, as an abstract method. The implementation given here can still be called from subclasses. The get_iterator()
method is also part of the MyIterable
abstract base class, but it does not have to be overridden in non-abstract derived classes.
The __subclasshook__()
class method defined here says that any class that has an __iter__()
method in its __dict__
(or in that of one of its base classes, accessed via the __mro__
list) is considered a MyIterable
too.
Finally, the last line makes Foo
a virtual subclass of MyIterable
, even though it does not define an __iter__()
method (it uses the old-style iterable protocol, defined in terms of __len__()
and __getitem__()
). Note that this will not make get_iterator
available as a method of Foo
, so it is provided separately.
Please login to continue.