Skip to content

Inheritance

Quality Score

Overall Score: 8.5/10 ✅ Excellent

  • Technical Accuracy: 31/35
  • Code Quality: 22/25
  • Educational Value: 20/25
  • Documentation: 12/15

Last reviewed: June 22, 2026

We are going to create a simple example that uses inheritance.

Class Driver is the base (abstract) class that represent a generic Driver. It will contain the one common attribute, one method concrete and one abstract.

Concrete methods are methods that can be called from the base class, and abstract methods are methods that needs to be implemented in the subclass.

src.intermediate.inheritance.inheritance.Driver dataclass

Bases: ABC

Abstract base class representing a driver with licensing.

This abstract class demonstrates inheritance patterns in Python using the ABC (Abstract Base Class) module. It defines common attributes and methods for all drivers while requiring subclasses to implement specific behavior through the abstract speed_limit method.

The class combines dataclass and ABC features to provide both automatic initialization and abstract method enforcement.

Attributes:

Name Type Description
novel_years int

Number of years after license issuance during which the driver is considered "novel" or inexperienced. Defaults to 0.

metric_unit str

Unit of speed measurement (e.g., 'mph' or 'km/h'). Defaults to empty string.

license_valid_from date | None

Date when the driver's license was issued. Used to calculate novel status. None if date is unknown.

Source code in src/intermediate/inheritance/inheritance.py
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
@dataclass
class Driver(ABC):
    """Abstract base class representing a driver with licensing.

    This abstract class demonstrates inheritance patterns in Python using the
    ABC (Abstract Base Class) module. It defines common attributes and methods
    for all drivers while requiring subclasses to implement specific behavior
    through the abstract speed_limit method.

    The class combines dataclass and ABC features to provide both automatic
    initialization and abstract method enforcement.

    Attributes:
        novel_years: Number of years after license issuance during which the
            driver is considered "novel" or inexperienced. Defaults to 0.
        metric_unit: Unit of speed measurement (e.g., 'mph' or 'km/h').
            Defaults to empty string.
        license_valid_from: Date when the driver's license was issued. Used
            to calculate novel status. None if date is unknown.
    """

    novel_years: int = 0
    metric_unit: str = ""
    license_valid_from: datetime.date | None = None

    def is_novel(self) -> bool:
        """Determine if the driver is in their "novel" period.

        A driver is considered novel if less time has passed since their license
        was issued than the configured novel_years period. This is commonly used
        to apply stricter rules for new drivers.

        Returns:
            True if the driver is within their novel period (inexperienced),
            False if they are experienced or if license_valid_from is None.
        """
        if self.license_valid_from is None:
            return False

        novel_days: int = 365 * self.novel_years
        novel_until: datetime.date = (
            self.license_valid_from + datetime.timedelta(days=novel_days)
        )
        return (
            novel_until
            >= datetime.datetime.now(
                tz=datetime.timezone.utc,
            ).date()
        )

    @abstractmethod
    def speed_limit(self) -> str:
        """Return the speed limit with metric unit for this driver type.

        This is an abstract method that must be implemented by all concrete
        subclasses. Each subclass defines its own speed limit rules based on
        local regulations and driver experience level.

        Returns:
            A string representing the speed limit with its unit (e.g., "70mph",
            "120km/h").

        Raises:
            NotImplementedError: If a subclass fails to implement this method.
        """
        raise NotImplementedError

Subclass UsaDriver represents a Driver in USA. It defines the novel years and the metric unit for the speed. Abstract method speed_limit is implemented.

src.intermediate.inheritance.inheritance.UsaDriver dataclass

Bases: Driver

Concrete Driver implementation for USA driving regulations.

This class inherits from Driver and implements USA-specific driving rules. In the USA, novel drivers have a 2-year period and speeds are measured in miles per hour (mph).

Attributes:

Name Type Description
novel_years int

Set to 2 years for USA drivers.

metric_unit str

Set to "mph" (miles per hour) for USA.

Source code in src/intermediate/inheritance/inheritance.py
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
@dataclass
class UsaDriver(Driver):
    """Concrete Driver implementation for USA driving regulations.

    This class inherits from Driver and implements USA-specific driving
    rules. In the USA, novel drivers have a 2-year period and speeds
    are measured in miles per hour (mph).

    Attributes:
        novel_years: Set to 2 years for USA drivers.
        metric_unit: Set to "mph" (miles per hour) for USA.
    """

    novel_years: int = 2
    metric_unit: str = "mph"

    def speed_limit(self) -> str:
        """Return the standard highway speed limit for USA drivers.

        USA drivers have a fixed highway speed limit of 70mph regardless
        of their novel status. This demonstrates how subclasses can
        implement abstract methods with their own logic.

        Returns:
            String representing the speed limit: "70mph".
        """
        return f"70{self.metric_unit}"

Subclass SpainDriver represents a Driver in Spain. It defines the novel years and the metric unit for the speed. Abstract method speed_limit is implemented.

src.intermediate.inheritance.inheritance.SpainDriver dataclass

Bases: Driver

Concrete Driver implementation for Spanish driving regulations.

This class inherits from Driver and implements Spain-specific driving rules. In Spain, novel drivers have a 1-year period with reduced speed limits, and speeds are measured in kilometers per hour (km/h).

Attributes:

Name Type Description
novel_years int

Set to 1 year for Spanish drivers.

metric_unit str

Set to "km/h" (kilometers per hour) for Spain.

Source code in src/intermediate/inheritance/inheritance.py
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
@dataclass
class SpainDriver(Driver):
    """Concrete Driver implementation for Spanish driving regulations.

    This class inherits from Driver and implements Spain-specific driving
    rules. In Spain, novel drivers have a 1-year period with reduced speed
    limits, and speeds are measured in kilometers per hour (km/h).

    Attributes:
        novel_years: Set to 1 year for Spanish drivers.
        metric_unit: Set to "km/h" (kilometers per hour) for Spain.
    """

    novel_years: int = 1
    metric_unit: str = "km/h"

    def speed_limit(self) -> str:
        """Return the highway speed limit based on driver experience.

        Spanish driving regulations enforce different speed limits for novel
        (inexperienced) and experienced drivers. Novel drivers are limited
        to 100km/h while experienced drivers can drive at 120km/h on highways.
        This demonstrates how subclasses can use inherited methods (is_novel)
        to implement their own logic.

        Returns:
            String representing the speed limit: "100km/h" for novel drivers
            or "120km/h" for experienced drivers.
        """
        if self.is_novel():
            return f"100{self.metric_unit}"
        return f"120{self.metric_unit}"

Common pitfalls

Don't forget to implement the abstract method in the subclass. If you don't, you will get a TypeError when you try to instantiate the subclass.

Additionally, don't make too many levels of inheritance. It is better to have a flat hierarchy than a deep one. You can always use composition instead of inheritance.