Search code examples
pythonabstract-classmultiple-inheritance

How can I create an abstract class that inherits from an abstract class in Python?


I'd like to define an abstract class which inherits from another abstract class.

class DataBuffer(ABC):
    def __init__(self):
        self.buffered_data = {}

class IMUDataBuffer(ABC, DataBuffer):
    def __init__(self):
        super(IMUDataBuffer, self).__init__()

    def update(self, message):
        timestamp = message['ts']
        x_val, y_val, z_val = message[self.message_key]
        self.buffered_data[timestamp] = (x_val, y_val, z_val)

class GyroscopeDataBuffer(IMUDataBuffer):
    def __init__(self):
        super(GyroscopeDataBuffer, self).__init__()
        self.message_key = 'gy'

class AccelerometerDataBuffer(IMUDataBuffer):
    def __init__(self, message):
        super(AccelerometerDataBuffer, self).__init__()
        self.message_key = 'ac'

In this example, the IMUDataBuffer should inherit methods from DataBuffer, but it itself will not ever be instantiated, and thus should be an abstract class.

This is the error that I receive with the above code:

TypeError: Cannot create a consistent method resolution order (MRO) for bases ABC, DataBuffer

As a cheap work around, I can define a message_key in the IMUDatabuffer, but this feels sloppy to me, as really the IMUDataBuffer shouldn't have a message_key property.

class IMUDataBuffer(DataBuffer):
    def __init__(self):
        super(IMUDataBuffer, self).__init__()
        self.message_key = None

What is the proper way to handle the inheritance here?


Solution

  • I propose to remove the ABC in IMUDataBuffer parent list as DataBuffer already has ABC as parent.

    ABC -> DataBuffer -> IMUDataBuffer -> Gyroscope
                                       -> Accelerometer
    

    The code would look like this:

    class ABC:
        pass
    
    class DataBuffer(ABC):  # <-- brings already all stuff from ABC
        def __init__(self):
            self.buffered_data = {}
    
    class IMUDataBuffer(DataBuffer):  # <-- ABC removed here
        def __init__(self):
            super(IMUDataBuffer, self).__init__()
    
        [...]
    

    Then the error disappears.