I found multiple (slightly different) ways to define abstract classes in Python. I read the documentation and also could not find an answer here on stackoverflow.
The main difference between the three examples (see code below) is:
Asets a new metaclassabc.ABCMetaexplicitlyBinherits fromabc.ABCCinherits fromobjectsbut defines@abc.abstractmethodclasses
It seems that A and B are not different (i.e. also B has the new metaclass abc.ABCMeta). However, class C remains of type type.
What are the impacts of not defining a metaclass for C? When is it necessary to define the metaclass or is it wrong/bad style to not define the abc.ABCMeta metaclass for an abstract class? Nonetheless, the class C seems to behave as I expect from an ABC.
import abc
class A(metaclass=abc.ABCMeta):
# Alternatively put __metaclass__ = abc.ABCMeta here
@abc.abstractmethod
def foo(self):
raise NotImplementedError
class B(abc.ABC):
@abc.abstractmethod
def foo(self):
raise NotImplementedError
class C(object):
@abc.abstractmethod
def foo(self):
raise NotImplementedError
class Aimpl(A):
def foo(self):
print("Aimpl")
class Bimpl(B):
def foo(self):
print("Bimpl")
class Cimpl(C):
#def foo(self):
# print("Cimpl")
pass
Aimpl().foo() # Aimpl
print(isinstance(Aimpl, A)) # False
print(issubclass(Aimpl, A)) # True
print(isinstance(Aimpl, abc.ABCMeta)) # True
print(type(A)) # <class 'abc.ABCMeta'>
print("---")
Bimpl().foo() # Bimpl
print(isinstance(Bimpl, B)) # False
print(issubclass(Bimpl, B)) # True
print(isinstance(Bimpl, abc.ABCMeta)) # True
print(type(B)) # <class 'abc.ABCMeta'>
print("---")
Cimpl().foo() # Cimpl
print(isinstance(Cimpl, C)) # False
print(issubclass(Cimpl, C)) # True
print(isinstance(Cimpl, abc.ABCMeta)) # False
print(type(C)) # <class 'type'>
print("---")