Introduction

In practice, code in abstract classes typically contains more than just the pass statement. Abstract classes serve as blueprints for derived classes, providing common attributes, methods, or properties that are meant to be implemented or extended by their subclasses.

While the abstract methods are indeed declared using @abstractmethod decorators with a pass statement in their implementation, the abstract class can have other concrete methods or properties that may provide default behavior or functionality shared among its subclasses.

Let's take the Shape example from earlier and expand it to include a concrete method in the abstract class:

from abc import ABC, abstractmethod, abstractproperty

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

    @abstractproperty
    def perimeter(self):
        pass

    def display_info(self):
        print(f"This is a {type(self).__name__} with area: {self.calculate_area()} and perimeter: {self.perimeter}.")

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius

    def calculate_area(self):
        return 3.14 * self.radius ** 2

    @property
    def perimeter(self):
        return 2 * 3.14 * self.radius

class Square(Shape):
    def __init__(self, side):
        self.side = side

    def calculate_area(self):
        return self.side ** 2

    @property
    def perimeter(self):
        return 4 * self.side

In this example, Shape now includes a concrete method display_info() that provides default behavior for displaying information about a shape. It does not have the @abstractmethod decorator, so it doesn't need a pass statement in its implementation. However, it relies on the abstract methods calculate_area() and perimeter(), which are implemented in the Circle and Square subclasses.

In summary, while abstract classes often have abstract methods with pass statements, they can also have concrete methods or properties that provide default behaviors or functionalities shared by their subclasses. This combination of abstract and concrete methods in abstract classes helps structure the code and encourage code reusability.

More Reasons

Using only "pass" in abstract classes for the implementation of abstract methods (i.e., using @abstractmethod) is a recommended practice for several reasons:

In summary, using only "pass" in abstract classes for the implementation of abstract methods is a best practice that promotes clarity, safety, and flexibility. It enables clear separation of concerns and encourages code reusability and extensibility, leading to a well-designed and maintainable codebase.