What's the point of abstract classes if they don't enforce method signatures?
python - Define an abstract method but require a subclass implementation - Stack Overflow
Simple explanation of abstract classes?
Should we use an abstract class when we know a parent class should never be directly accessed?
Videos
I was surprised to see the Python abstract classes don't enforce anything except the override and method name. I can see why in Python enforcing parameter data-types would probably not work, but the number of parameters and parameter names ought to be enforced.
I've always thought the point of abstract classes was to ensure that any inheritor of the class would would work with existing code to run the abstract methods defined in the super class. The whole point was to enforce method signatures.
It seems to me that Python's implantation of abstract classes has very little utility. Does anyone even use them? What for?
In Python, you usually avoid having such abstract methods alltogether. You define an interface by the documentation, and simply assume the objects that are passed in fulfil that interface ("duck typing").
If you really want to define an abstract base class with abstract methods, this can be done using the abc module:
from abc import ABCMeta, abstractmethod
class Abstract(metaclass=ABCMeta):
def use_concrete_implementation(self):
print(self._concrete_method())
@abstractmethod
def _concrete_method(self):
pass
class Concrete(Abstract):
def _concrete_method(self):
return 2 * 3
Again, that is not the usual Python way to do things. One of the main objectives of the abc module was to introduce a mechanism to overload isinstance(), but isinstance() checks are normally avoided in favour of duck typing. Use it if you need it, but not as a general pattern for defining interfaces.
When in doubt, do as Guido does.
No underscore. Just define the "abstract method" as a one-liner which raises NotImplementedError:
class Abstract():
def ConcreteMethod(self):
raise NotImplementedError("error message")
Note I do not think that abc inherently solves what I'm looking for.
Actually abc is exactly what you're looking for. Defining an implementation in
the base class but decorating it as abstract requires deriving classes to redefine it.
Of course this has the side effect of preventing you from instantiating the base class,
which I assume is OK in your use case.
import abc
# inheritance from abc.ABC is important, as otherwise the decorators don't do anything
class AbstractClass(abc.ABC):
@abc.abstractmethod
def amethod(self):
# some code that should always be executed here
print("Base implementation")
class ActualClass(AbstractClass):
# will return TypeError: Can't instantiate abstract class ActualClass with abstract methods amethod if not redefined
def amethod(self):
# Actual class code
print("Actual implementation")
# And execute the super class code. (only one super class so less confusing)
super().amethod()
a = ActualClass()
a.amethod()
Test like this?
class AbstractClass(object):
def amethod(self):
# some code that should always be executed here
print(" AbstractClass.amethod()")
# But, since we're the "abstract" class
# force implementation through subclassing
if self.__class__ == AbstractClass:
raise NotImplementedError
class ActualClass(AbstractClass):
def amethod(self):
# Actual class code
print(" ActualClass.amethod()")
# And execute the super class code.
super(ActualClass, self).amethod()
#a = AbstractClass()
#a.amethod()
b = ActualClass()
b.amethod()