14

I would like to know if it is possible to use multiple inheritance with abstract base class in python. It seems like it should be possible but can't find a statement one way or the other.

The basic ABC example:


from abc import ABC, abstractmethod


class BaseABC(ABC):

    @abstractmethod
    def hello(self):
        pass


class Child(BaseABC):
    pass


child = Child()

This will fail due to "hello" not being implemented in "Child".

What I would like is to know how to combine ABC with multiple inheritance. I would like to make either the "BaseABC" or "Child" to inherit also from some other separate class. Explicitly:


from abc import ABC, abstractmethod


class BaseABC(ABC, dict):

    @abstractmethod
    def hello(self):
        pass


class Child(BaseABC):
    pass


child = Child()

This does not fail in the way expected as the first case does. Also:


from abc import ABC, abstractmethod


class BaseABC(ABC):

    @abstractmethod
    def hello(self):
        pass


class Child(BaseABC, dict):
    pass


child = Child()

This does not fail either. How can I require "Child" to implement "hello"?

1 Answer 1

7

The issue is with inheriting from a dict, which is probably better explained by these guys:

From my understanding, the built-in list, dict, and set types have in-lined a lot of code for performance. Essentially, they’ve copy-pasted the same code between many different functions to avoid extra function calls and make things a tiny bit faster.

I haven’t found a reference online that explains why this decision was made and what the consequences of the alternatives to this choice were. But I mostly trust that this was done for my benefit as a Python developer. If dict and list weren’t faster this way, why would the core developers have chosen this odd implementation?

It happens, because Python built-in dict is implemented on C and its methods are independent of one another. It is done for performance, I guess.

So depending on little what you want to do with your subclassed dict you could go with MutableMapping as suggested in https://stackoverflow.com/a/3387975/14536215 or with UserDict (which is a subclass of MutableMapping) such as:

from abc import ABC, abstractmethod
from collections import UserDict


class BaseABC(ABC):

    @abstractmethod
    def hello(self):
        pass

class Child(BaseABC, UserDict):
    pass


child = Child()
Sign up to request clarification or add additional context in comments.

4 Comments

Maybe i missed it on the links but i can't find any explanation on why inheriting from dict would prevent the requirement of implementing the abstract method?
Image
do you want the dictionary to be local to the class or shared by class like a static variable
Thanks for that Tzane. Ok, seems I chose a bad case, I thought dict would be sufficiently generic. Seems to work on my own custom class, let's hope it works on the class I need in practice!
@tbjorch I don't think it was explicitly said why this doesn't work, but both sources reference the back end implementation of dict ( list and set) is somehow made "static" to gain better performance.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.