Difficulty: Advanced
How does super() work in Python with multiple inheritance? What are mixins?
Python uses Method Resolution Order (MRO) - a linear ordering of base classes computed by the C3 linearization algorithm.
super() follows the MRO - it calls the next class in the MRO, not necessarily the direct parent. This is crucial for cooperative multiple inheritance.
Mixins: small, focused classes that add behavior to other classes without being used standalone. They should not define __init__ (or call super().__init__() cooperatively).
__init_subclass__: called whenever a class is subclassed, enabling plugin registries and validation.
class A:
def method(self):
print('A.method')
super().method() # Cooperative - passes to next in MRO
class B(A):
def method(self):
print('B.method')
super().method()
class C(A):
def method(self):
print('C.method')
super().method()
class D(B, C):
def method(self):
print('D.method')
super().method()
print(D.__mro__) # D -> B -> C -> A -> object
d = D()
d.method()
# D.method -> B.method -> C.method -> A.method
# super() follows MRO, not just the parent
# B.super() goes to C (next in D's MRO), not A!
# Verify MRO
for cls in D.__mro__:
print(cls.__name__)
super() in B calls C, not A - it follows the MRO of the instance (D), not B's own parent. This is cooperative multiple inheritance.
# Mixin: no __init__, no standalone use
class LoggedMixin:
def __getattribute__(self, name):
result = super().__getattribute__(name)
if callable(result):
print(f'Accessing: {name}')
return result
class JSONMixin:
def to_json(self):
import json
return json.dumps(vars(self))
@classmethod
def from_json(cls, data):
import json
return cls(json.loads(data))
# Compose with multiple inheritance
class User(JSONMixin, LoggedMixin):
def __init__(self, name, email):
self.name = name
self.email = email
u = User('Alice', 'alice@example.com')
print(u.to_json())
# __init_subclass__: plugin registry
class BasePlugin:
_plugins = {}
def __init_subclass__(cls, plugin_name=None, kwargs):
super().__init_subclass__(kwargs)
if plugin_name:
BasePlugin._plugins[plugin_name] = cls
class EmailPlugin(BasePlugin, plugin_name='email'):
def send(self): print('Sending email')
class SMSPlugin(BasePlugin, plugin_name='sms'):
def send(self): print('Sending SMS')
print(BasePlugin._plugins)
# {'email': EmailPlugin, 'sms': SMSPlugin}
__init_subclass__ runs when any subclass is defined - enables automatic plugin registration without explicit registration calls.
__init_subclass__, ABC, mixin, multiple inheritance, super()