Python abstraction with abstract classes

Specify required behavior while leaving implementation to subclasses.

Python
from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height
    def area(self):
        return self.width * self.height

shape = Rectangle(3, 4)
print(shape.area())
assert Rectangle(0, 4).area() == 0
Output
12

Explanation

An abstract base class can declare methods that concrete subclasses must implement. It describes what callers may request without prescribing one implementation.

Shape requires area. Rectangle supplies it using width and height. Instantiating Shape itself would raise TypeError because its abstract method is not implemented.

Explore the dry run
Guided walkthroughReady
1from abc import ABC, abstractmethod
2
3class Shape(ABC):
4 @abstractmethod
5 def area(self):
6 pass
7
8class Rectangle(Shape):
9 def __init__(self, width, height):
10 self.width = width
11 self.height = height
12 def area(self):
13 return self.width * self.height
14
15shape = Rectangle(3, 4)
16print(shape.area())
17assert Rectangle(0, 4).area() == 0

Follow the example

Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.

View the complete dry-run table
Prepared trace of the published program. Some rows group repeated iterations.
Step / lineWhat happensState after stepOutput so far
Define the abstract contract.—
—
Create a concrete instance.width = 3, height = 4
—
Compute the rectangle implementation of area.return = 12
—
Print the result.return = 12
12
Check a zero-width rectangle.return = 12
12

Cost and common mistakes

O(1) arithmetic operations and O(1) object state.

  • This example assumes nonnegative numeric dimensions.
  • An abstract base class is useful for an explicit contract, but is not required for all Python polymorphism.

Try it yourself

Implement Square with one side and an area method.

Reveal answer and reasoning

Store side in __init__, return side * side, and check that Square(5).area() is 25.

Further reading