The SomeClass class has a custom metaclass. You will need to create a metaclass which inherits from both ABCMeta and this custom metaclass, then use it as the metaclass for MyClass. Without knowing more about this custom metaclass, I cannot determine a correct way to do this in the general case, but it will probably look like one of these possibilities:

class DerivedMeta(ABCMeta, type(SomeClass)):
    pass

class DerivedMeta(type(SomeClass), ABCMeta):
    pass

It's unlikely but possible you will also need to override one or more methods to ensure correct metaclass interactions.

Answer from Kevin on Stack Overflow
🌐
Python
docs.python.org › 3 › library › abc.html
abc — Abstract Base Classes
With this class, an abstract base class can be created by simply deriving from ABC avoiding sometimes confusing metaclass usage, for example: ... Note that the type of ABC is still ABCMeta, therefore inheriting from ABC requires the usual precautions regarding metaclass usage, as multiple inheritance may lead to metaclass conflicts.
🌐
GeeksforGeeks
geeksforgeeks.org › python › multiple-inheritance-in-python
Multiple Inheritance in Python - GeeksforGeeks
The code demonstrates multiple inheritance where Class4 inherits from Class2 and Class3; calling obj.m() executes Class2’s method because, according to Python’s MRO, Class2 is checked before Class3.
Published   December 27, 2025
🌐
Medium
elfi-y.medium.com › inheritance-in-python-with-abstract-base-class-abc-5e3b8e910e5e
Inheritance in Python with Abstract Base Class(ABC) | by E.Y. | Medium
January 13, 2021 - Also, it’s just very difficult to manage inheritance relationship without proper subclassing anyway. For example, a Member and SupermarketStock class can both can len(). But they are not the same thing even if they implement the same methods. And that’s where Abstract Base Classes(ABC) come to rescue.
🌐
Pybites
pybit.es › articles › elevate-your-python-harnessing-the-power-of-abstract-base-classes-abcs
Elevate Your Python: Harnessing The Power Of Abstract Base Classes (ABCs) - Pybites
February 21, 2024 - Note: In the example above, we’ve used the ABCMeta metaclass directly for defining the abstract base class. However, Python provides a more modern and succinct way to achieve the same result using the ABC class from the abc module. Note that the type of ABC is still ABCMeta, therefore inheriting from ABC requires the usual precautions regarding metaclass usage, as multiple ...
🌐
Medium
medium.com › @pouyahallaj › introduction-1616b3a4a637
Python Protocols vs. ABCs: A Comprehensive Comparison of Interface Design | Medium
May 29, 2023 - To define an ABC in Python, you ... my_method(self): pass · In the example above, we define an ABC called MyABC that inherits from the ABC base class provided by the abc module....
🌐
Duke
fintechpython.pages.oit.duke.edu › jupyternotebooks › 1-Core Python › answers › rq-26-answers.html
Core Python / Inheritance — Programming for Financial Technology
This example largely follows the same code from the first example, but with the Investment class declared as abstract. Importing ABC and abstractmethod: The ABC class from the abc module is used to define an abstract base class. The abstractmethod decorator is used to declare abstract methods. Defining the Abstract Class (Investment): The Investment class inherits ...
Find elsewhere
🌐
Programiz
programiz.com › python-programming › multiple-inheritance
Python Multiple Inheritance (With Examples)
In the above example, the Bat class is derived from two super classes: Mammal and WingedAnimal. Notice the statements, b1 = Bat() b1.mammal_info() b1.winged_animal_info() Here, we are using b1 (object of Bat) to access mammal_info() and winged_animal_info() methods of the Mammal and the ...
🌐
Python Course
python-course.eu › oop › the-abc-of-abstract-base-classes.php
20. The 'ABC' of Abstract Base Classes | OOP | python-course.eu
Like in other cases of "normal" inheritance, the abstract method can be invoked with super() call mechanism. This enables providing some basic functionality in the abstract method, which can be enriched by the subclass implementation. from abc import ABC, abstractmethod class AbstractClassExample(ABC): @abstractmethod def do_something(self): print("Some implementation!") class AnotherSubclass(AbstractClassExample): def do_something(self): super().do_something() print("The enrichment from AnotherSubclass") x = AnotherSubclass() x.do_something()
🌐
Mimo
mimo.org › glossary › python › inheritance
Python Inheritance: Syntax, Usage, and Examples
Understanding the MRO helps avoid surprises when using multi inheritance Python supports. This setup is one of the types of inheritance you’ll see discussed when people compare inheritance models across languages. Sometimes, you want to create a class that shouldn't be instantiated but should only serve as a blueprint. That’s where abstract base classes come in. ... from abc import ABC, abstractmethod class Shape(ABC): @abstractmethod def area(self): pass class Circle(Shape): def __init__(self, radius): self.radius = radius def area(self): return 3.14 * self.radius ** 2
🌐
Rip Tutorial
riptutorial.com › multiple inheritance
Python Language Tutorial => Multiple Inheritance
for below example only Foo class init method getting called Bar class init not getting called · class Foo(object): def __init__(self): print "foo init" class Bar(object): def __init__(self): print "bar init" class FooBar(Foo, Bar): def __init__(self): print "foobar init" super(FooBar, self).__init__() a = FooBar() ... But it doesn't mean that Bar class is not inherit.
🌐
Python Course
python-course.eu › oop › multiple-inheritance.php
11. Multiple Inheritance | OOP | python-course.eu
March 24, 2024 - We want to introduce the principles of multiple inheritance with an example. For this purpose, we will implement to independent classes: a "Clock" and a "Calendar" class. After this, we will introduce a class "CalendarClock", which is, as the name implies, a combination of "Clock" and "Calendar".
Top answer
1 of 1
1

There are generally many good ways to implement this. However, everyone have their own preferences, so mostly which of the following you use is up to you. Here's the three approaches:

  1. Do it the way you are currently implementing it. For a basic structure, it'll be something similar to this:
from abc import ABCMeta

class Abstract(metaclass=ABCMeta):
    def write(self):
        raise NotImplementedError()

class Mixin():
    def meth1(self, *args, **kwargs):
        """ do something here"""

class ActualUsefulImplementedClass(Abstract, Mixin):
    """ write your methods here. You will have access to all the helper methods of the mix-in class."""
  1. Implementing the methods as functions (presumably in another file in the same directory as the current file) and call them from inside the class will also be OK:
from abc import ABCMeta
from helpers import func1, func2, func3, ...

class Abstract(metaclass=ABCMeta):
    def write(self):
        raise NotImplementedError()

class ActualUsefulImplementedClass(Abstract, Mixin):
    """ write your methods here. Access the helper functions imported above directly in your methods."""
    # for example
    def do_something(self, *args, **kwargs):
        func1(*args)

This approach does have it's drawbacks, namely:

  • If by any chance your helper methods acts on an instance of some self-defined class, then this approach will break. Of course, you can pass-in the instance as an argument, but that is a very, very bad idea in terms of software engineering ideas and principles.
  • Also, if you want to inherit them once and have access to them without additional code for all of the ActualUsefulImplementedClass's subclasses, then this approach doesn't fit the bill.
  • Finally, if you want a strictly OOP approach, or don't want the helper functions to pollute your current module scope's namespace, then this isn't the best fit as well.
  1. Similar to the first approach stated above (number 1), but create another middle-level class that doesn't use the mix-in. It will be something like the following:
from abc import ABCMeta

class Abstract(metaclass=ABCMeta):
    def write(self):
        raise NotImplementedError()

class Mixin():
    def meth1(self, *args, **kwargs):
        """ do something here"""

class MiddleMan(Abstract):
    """ write your methods here. You will not have access to the helper methods of the mix-in class."""

class ActualUsefulImplementedClass(MiddleMan, Mixin):
    """ You will have both the actual method implementations and the helper methods here without much or any code."""

However, the above code will only work if you don't need the helper methods inside your methods' implementations and only need them outside of the class. If you need them inside the methods' code, then use the first approach. If you only need the helpers outside of the class, then use this approach.


Note: I use docstrings in the line immediately after the class or method definition line whenever applicable. It describes some of the abilities and limitations of the approach, so please read them as well.

🌐
GitHub
github.com › python › cpython › issues › 104797
Cannot use multiple inheritance with `collections.abc.Buffer` and `typing.Protocol` · Issue #104797 · python/cpython
February 21, 2023 - 3.12only security fixesonly security fixes3.13bugs and security fixesbugs and security fixesstdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytopic-typingtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error ... Various stdlib classes are treated as protocols by type checkers, but are actually ABCs at runtime (for performance reasons). Examples include contextlib.AbstractContextManager and collections.abc.Iterable. These classes are special-cased in typing.py to allow for multiple inheritance with typing.Protocol, so that the interface can be extended:
Published   May 23, 2023
Author   AlexWaygood
🌐
Real Python
realpython.com › inheritance-composition-python
Inheritance and Composition: A Python OOP Guide – Real Python
January 11, 2025 - The Employee class in the example above is what is called an abstract base class. Abstract base classes exist to be inherited, but never instantiated. Python provides the abc module to formally define abstract base classes.
Top answer
1 of 3
5

Using Python's multiple inheritance (MI) for interfaces, abstract base classes, mixins, or similar techniques is perfectly fine. In most cases, the MRO produces intuitive results.

However, object initialization under multiple inheritance is really tricky. In Python you cannot combine multiple classes per MI unless all participating classes have been designed for MI. The issue is that the __init__() method cannot know from which class it will be called and what the signature of the super().__init__() method will be. Effectively, this means that MI constructors:

  • must call the super().__init__()
  • must only take arguments by name, not by position
  • must forward any **kwargs to the super().__init__()
  • must not warn on unexpected arguments

Where possible, the better alternative is to avoid __init__() methods for interface-like classes, and instead express requirements through abstract methods. For example, instead of a BananaContainer class, we might write this interface/ABC:

import abc  # abstract base class

class BananaContainer(abc.ABC):
  @property
  @abc.abstractmethod
  def bananas(self) -> list:
    raise NotImplementedError

If a class wants to be a BananaContainer, it would have to implement that property.

In general, it is perfectly alright if you have a class that inherits from multiple interfaces or mixins. Aside from name collisions, the above __init__() problems, and general API bloat of the class, no noteworthy issues arise.


The second part of your question proposes a capability-based approach instead of using inheritance. Using composition instead of inheritance is often a very very good idea. For example, you eliminate the initialization problems by design. It also tends to lead to more explicit APIs that are easier to navigate and avoid name clashes. There should be some method that either returns an object representing a capability, or None if the capability isn't supported.

But these capabilities can be implemented in different ways: either by using normal composition, or by storing the capabilities in your own data structures.

  • Unless you have special needs for the object model, stick to the language. Store methods in normal object fields, provide normal methods to access them. This leads to a more comfortable API, and is more likely to support auto-completer and type-checkers.

  • If you need to modify the available capabilities of an object at run-time, and need to introduce new kinds of capabilities at run-time, then using a dictionary may be appropriate. But at this point you are inventing your own object system. This may be a good idea e.g. in games that have complex capability systems where new capabilities shall be defined in configuration files.

    Most software does not have these requirements, and does not benefit from that kind of flexibility.

    Additionally, Python's built-in object system is flexible enough that you could create new types and new methods without having to create a new object system. Builtins like getattr(), setattr(), hasattr(), and the type() constructor come in handy here.

I would likely express an object that can have both AppleContainer and BananaContainer capabilities like this:

class BananaContainer:
  ...

class AppleContainer:
  ...

class HasCapabilities:
  def __init__(self, x, y, z):
    # somehow determine the appropriate capabilities and initialize them
    self._banana_container = BananaContainer(y) if x else None
    self._apple_container = AppleContainer(y)

  @property
  def as_banana_container(self) -> Optional[BananaContainer]:
    return self._banana_container

  @property
  def as_apple_container(self) -> Optional[AppleContainer]:
    return self._apple_container

o = HasCapabilities(...)
bc = o.as_banana_container
if bc is not None:
  bc.do_banana_things()

Or with Python 3.8 assignment expressions:

if (bc := o.as_banana_container) is not None:
  bc.do_banana_things()

If you want to have some custom mechanisms for reflection over capabilities, you can implement that on top of this solution, with some amount of boilerplate. If we want to be MI-safe, we might declare the following base class that all capability-having classes need to inherit:

class CapabilityReflection:
  # a base implementations so that actual implementations
  # can safely call super()._get_capabilities()
  def _list_capabilities(self):
    return ()

  def all_capabilities(self):
    """deduplicated set of capabilities that this object supports."""
    set(self._list_capabilities())

  def get_capability(self, captype):
    """find a capability by its type. Returns None if not supported."""
    return None

which in the above case would have been implemented as:

class HasCapabilities(CapabilityReflection):
  ...
  def _list_capabilities(self):
    caps = [  # go through properties in case they have been overridden
      self.as_banana_container,
      self.as_apple_container,
    ]
    yield from (cap for cap in caps if cap is not None)
    yield from super()._list_capabilities()

  def get_capability(self, captype):
    if captype == BananaContainer:
      return self.as_banana_container
    if captype == AppleContainer:
      return self.as_apple_container
    return super().get_capability(captype)
2 of 3
2

In order to ensure a class has some properties, I make base "interface" classes

While this is a common design pattern in statically typed languages, Python programmers consider more idiomatic to use duck typing for your classes. Since the language is dynamically typed, if you have Foo and Bar classes that both can contain bananas, you are free to call unknown.banana on a variable that can be either. If unknown can be an object that don't implement banana, you can also use getattr or try/except AttributeError blocks. The explicit interface is just bloat over features the language already support.

If for any reason you don't want to get rid of these interfaces, then you could at least use multiple inheritance. It exists because it has uses and is correct to use in many cases.

can it hit us back later with problems like method resolution order or name collisions ?

In your multiple inheritance declaration, the first object has priority when it comes to symbol collisions. In some cases, it's a feature, but you have to be careful this doesn't cause unintended overrides, like you would when defining methods and properties in a child class.

The capability suggestion is overly defensive over inheritance mechanisms. Making sure you don't accidentally override is your responsibility, but it shouldn't be a huge burden. If it happens to be one, it's likely you have other problems. And in cases you are not sure of the symbols contained in a class and want to use it as a black box, it may be appropriate to favor composition.