Search⌘ K
AI Features

The Diamond Problem

Explore the diamond problem in Python's multiple inheritance, understand how naive initialization can cause issues, and learn how Python's method resolution order and super() function solve these challenges by ensuring each method is called correctly and only once.

Overview

We can use multiple inheritance to add this new class as a parent of our existing Friend class. The tricky part is that we now have two parent __init__() methods, both of which need to be called. And they need to be called with different arguments. How do we do this? Well, we could start with a naive approach for the Friend class, also:

Python 3.10.4
class Friend(Contact, AddressHolder):
def __init__(
self,
name: str,
email: str,
phone: str,
street: str,
city: str,
state: str,
code: str,
) -> None:
Contact.__init__(self, name, email)
AddressHolder.__init__(self, street, city, state, code)
self.phone = phone

Problem in multiple inheritance

In this example, we directly call the __init__() function on each of the superclasses and explicitly pass the self argument. This example technically works; we can access the different variables directly in the class. But there are a few problems.

  • First, it is possible for a superclass to remain uninitialized if we neglect to explicitly call the initializer. That wouldn’t break this example, but it could cause hard-to-debug program crashes in common scenarios. We would get a lot of strange-looking AttributeError exceptions in classes where there’s clearly an __init__() method. It’s rarely obvious the __init__() method wasn’t actually used.

  • A more insidious possibility is a superclass being called multiple times because of the organization of the class hierarchy. Look at this inheritance diagram:

Multiple inheritance implementation
Multiple inheritance implementation

The __init__() method from the Friend class first calls __init__() on the Contact class, which implicitly ...