The contract of an ADT should not live only in documentation: we write it in code with abc.ABC or typing.Protocol, implement it on two different structures and check it with shared tests. This lesson continues ADT vs data structure in Python; the language tools themselves are covered in the lessons on abstract base classes and generics and protocols.
ABC: an enforced interface
The class Stack inherits from ABC and marks push, pop and __len__ as abstract. If a subclass forgets one, creating an object raises TypeError: the mistake is caught before use. Ready-made methods such as is_empty come free with every implementation.
from abc import ABC, abstractmethod
class Stack(ABC):
@abstractmethod
def push(self, x): ...
@abstractmethod
def pop(self): ...
@abstractmethod
def __len__(self): ...
def is_empty(self):
return len(self) == 0
class Broken(Stack):
def push(self, x):
pass
try:
Broken()
except TypeError as e:
print(type(e).__name__)TypeError