The NotImplementedError in abstract methods means a subclass failed to provide its own implementation for a method that the parent abstract class declared as mandatory.

Here’s what’s actually broken at the system level: The Python interpreter’s type-checking mechanism, specifically within the abc (Abstract Base Classes) module, identified that an instance of a class inheriting from an abstract class was created, but that instance’s class did not override a method marked as @abstractmethod. This is a contract violation: the abstract class requires subclasses to implement certain methods, and this requirement was not met, preventing the object from being fully functional according to its declared type.

Common Causes and Fixes

  1. Missing Method Implementation:

    • Diagnosis: Inspect the traceback. It will pinpoint the exact abstract method that was not implemented. Then, check the subclass definition to see if that method is present.
    • Fix: Add the missing method to the subclass. For example, if MyAbstractClass has an @abstractmethod called process_data, and your MyConcreteClass inherits from it, ensure MyConcreteClass has a process_data method defined.
    • Why it works: This fulfills the contract defined by the abstract base class. The interpreter verifies that all abstract methods have concrete implementations before allowing an instance of the subclass to be created.
    from abc import ABC, abstractmethod
    
    class MyAbstractClass(ABC):
        @abstractmethod
        def process_data(self, data):
            pass
    
    # Incorrect: Missing process_data
    class MyConcreteClass(MyAbstractClass):
        def other_method(self):
            print("Doing something else")
    
    # Corrected:
    class MyConcreteClass(MyAbstractClass):
        def process_data(self, data):
            print(f"Processing: {data}")
        def other_method(self):
            print("Doing something else")
    
    # my_instance = MyConcreteClass() # This would raise the error if process_data was missing
    
  2. Typo in Method Name:

    • Diagnosis: The traceback shows process_data is missing, but you swear you implemented it. Carefully compare the method name in the abstract class with the one in your subclass. Look for simple typos like proces_data, process_dataa, or case mismatches (Process_data).
    • Fix: Correct the method name in the subclass to exactly match the abstract method’s name.
    • Why it works: Python is case-sensitive and exact-match oriented. Correcting the name ensures the subclass’s method is recognized as the implementation of the abstract method.
  3. Method Signature Mismatch (Less Common for NotImplementedError, but related):

    • Diagnosis: While NotImplementedError usually means the method is absent, a significant signature mismatch could sometimes lead to unexpected behavior or make the interpreter think it’s not a valid override. Check if the number of arguments (excluding self) and their types (if using type hints) match the abstract method.
    • Fix: Ensure the subclass method’s signature precisely matches the abstract method’s signature, including positional and keyword arguments.
    • Why it works: The @abstractmethod decorator and the abc module rely on method signature matching to confirm an override. A mismatch can prevent this association.
    from abc import ABC, abstractmethod
    
    class MyAbstractClass(ABC):
        @abstractmethod
        def calculate(self, x: int, y: int) -> int:
            pass
    
    # Incorrect signature (missing y)
    class MyConcreteClass(MyAbstractClass):
        def calculate(self, x: int): # Error here
            return x * 2
    
    # Corrected signature
    class MyConcreteClass(MyAbstractClass):
        def calculate(self, x: int, y: int) -> int:
            return x + y
    
  4. Inheriting from a Class That Looks Concrete but is Abstract:

    • Diagnosis: You might be inheriting from a class that itself inherits from an abstract class and is supposed to be concrete, but it failed to implement all the abstract methods. The error then appears when you try to instantiate your class.
    • Fix: Trace the inheritance chain. Find the intermediate class that fails to implement the abstract method and add the missing implementation there.
    • Why it works: Abstractness propagates. If an intermediate class doesn’t fulfill the abstract contract, all its subclasses are also considered abstract until the contract is met.
    from abc import ABC, abstractmethod
    
    class GrandAbstract(ABC):
        @abstractmethod
        def essential_task(self):
            pass
    
    class ParentClass(GrandAbstract):
        # Missing essential_task implementation
        pass
    
    class ChildClass(ParentClass):
        def another_task(self):
            print("Doing something else")
    
    # child_instance = ChildClass() # This will raise NotImplementedError for GrandAbstract.essential_task
    
  5. Using super() Incorrectly (or not at all) in a Method that should call the abstract parent:

    • Diagnosis: This is a bit more nuanced. If your abstract method does have a default implementation in an intermediate class (not strictly abstract, but has a pass or some logic), and your concrete subclass doesn’t call super().abstract_method(), it might not be "executing" the full contract. However, the NotImplementedError itself typically arises when the method is entirely missing, not just when super() isn’t called. This is more about ensuring all required logic runs.
    • Fix: If the abstract method has a base implementation you need to extend, ensure your subclass method calls super().abstract_method(*args, **kwargs).
    • Why it works: super() allows you to call methods from parent classes. If a base class provided partial functionality for an abstract method, calling super() ensures that functionality is included, in addition to your subclass’s specific logic.
  6. Forgetting to Inherit from ABC:

    • Diagnosis: You’ve defined methods with @abstractmethod, but you forgot to make your class inherit from abc.ABC. The @abstractmethod decorator on its own doesn’t enforce anything without the ABC metaclass.
    • Fix: Ensure your abstract class inherits from abc.ABC.
    • Why it works: The ABC metaclass is what enables the abstract base class machinery. Without it, the @abstractmethod decorator is largely decorative, and the abc module can’t enforce the implementation requirement.
    from abc import ABC, abstractmethod
    
    # Incorrect: Not inheriting from ABC
    class MyAbstractClass:
        @abstractmethod
        def process_data(self, data):
            pass
    
    class MyConcreteClass(MyAbstractClass):
        # This would NOT raise an error even if process_data is missing,
        # because MyAbstractClass isn't truly abstract.
        pass
    
    # Corrected:
    class MyAbstractClass(ABC): # Inherits from ABC
        @abstractmethod
        def process_data(self, data):
            pass
    
    class MyConcreteClass(MyAbstractClass):
        # Now, if process_data is missing, an error will occur.
        pass
    

After fixing the NotImplementedError, the next error you’ll likely encounter is a TypeError if you try to instantiate an abstract class directly.

Want structured learning?

Take the full Python course →