Mixins
Learn the REAL Python OOP system used by Django, FastAPI, SQLAlchemy, Pydantic, PyTorch, and Scrapy. Master mixins, multiple inheritance, and professional OOP patterns used in large-scale frameworks.
Learn Python, JavaScript, Java and more with free interactive lessons, real projects and AI-powered help. Beginner-friendly.
Part of the free Python course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
🔥 Mixins, Multiple Inheritance & OOP Patterns
This lesson teaches the REAL Python OOP system used by:
This is how large Python frameworks organise reusable behaviour at scale.
⭐ 1. What Are Mixins?
Mixins = adding reusable abilities, not designing base types.
⭐ 2. Why Mixins Exist
Instead, they break features into "behaviour modules":
This avoids the inheritance mess of shoving everything into one giant parent class.
⭐ 3. When NOT To Use Mixins
⚙️ 4. Multiple Inheritance — How Python Makes This Work
This determines which class Python checks first when calling a method.
⭐ 5. How to View the MRO
🔷 6. The Diamond Problem (and Python's solution)
⭐ 7. Why super() Matters in Multiple Inheritance
This allows cooperative multiple inheritance.
⚡ 8. Designing Cooperative Mixins
If every class cooperates, Python can thread all behaviours together.
This is how Django CBVs (Class-Based Views) work internally.
🔶 9. Mixins Should NOT Have __init__
Mixins generally avoid __init__ because it breaks cooperative inheritance.
Otherwise, your mixin may block other parents from initialising.
⭐ 10. Real-World Mixin Examples
🧠 11. Interface Mixins (Behaviour Contracts)
🔥 12. Multiple Inheritance for Role Composition
This is scalable for 10+ behaviour components.
🧩 13. Composition vs Inheritance (Critical Design Decision)
🧱 14. Pattern: Behaviour Trees With Mixins
🧵 15. Pattern: Mechanical Mixins (Deep Automation)
📋 Quick Reference — Mixins & Multiple Inheritance
You can now compose reusable behaviours with mixins and reason about MRO — the same pattern Django's class-based views use.
Up next: Design Patterns — apply proven solutions to common software architecture problems.
Practice quiz
What best describes a mixin?
- A large base class meant to be instantiated directly
- A function that returns a class
- A small class that provides one specific reusable behaviour, not meant to stand alone
- A module of unrelated helper functions
Answer: A small class that provides one specific reusable behaviour, not meant to stand alone. A mixin is a small class adding one capability that you mix into other classes; it is not instantiated on its own.
For 'class C(A, B): pass' where both A and B define greet(), which greet() runs for C()?
- A.greet, because A comes first in the MRO
- B.greet, because B is listed last
- Neither; it raises an error
- Both run in sequence
Answer: A.greet, because A comes first in the MRO. Python follows the MRO left to right, so A (listed first) is found before B.
What does C.__mro__ (or C.mro()) give you?
- The class's instance attributes
- A list of mixins only
- The class's metaclass
- The Method Resolution Order — the linear order Python searches for methods
Answer: The Method Resolution Order — the linear order Python searches for methods. __mro__ is the ordered tuple of classes Python checks when resolving attributes and methods.
What does Python use to compute a deterministic MRO and solve the diamond problem?
- Random ordering
- C3 linearization
- Depth-first left-to-right only
- Alphabetical ordering of class names
Answer: C3 linearization. CPython uses C3 linearization to produce a consistent, unambiguous MRO.
In multiple inheritance, what does super() actually do?
- Calls the NEXT class in the MRO chain
- Always calls the single direct parent class
- Calls the object base class directly
- Skips all parent classes
Answer: Calls the NEXT class in the MRO chain. super() delegates to the next class in the MRO, which is what makes cooperative inheritance work.
For 'class D(A, B, C):' where D.process calls super().process(), what is D's MRO order?
- D, C, B, A, object
- A, B, C, D, object
- D, A, B, C, object
- D, object, A, B, C
Answer: D, A, B, C, object. The MRO is D, A, B, C, object — left to right across the bases, then object.
For a cooperative mixin to not break the chain, its overriding method should:
- Never call super()
- Call super() and accept *args, **kwargs
- Return None immediately
- Define its own __init__ that ignores parents
Answer: Call super() and accept *args, **kwargs. Cooperative mixins call super() and pass through *args/**kwargs so every class in the MRO runs.
Why do mixins generally avoid defining __init__?
- Because __init__ is illegal in mixins
- Because mixins cannot store data ever
- Because __init__ makes them abstract
- Because it can break cooperative initialization across the MRO
Answer: Because it can break cooperative initialization across the MRO. A poorly written mixin __init__ can block other parents from initializing; if needed it must call super().__init__.
In 'class User(LoggingMixin, ValidationMixin, BaseModel)', calling user.save() that chains super() prints in what order?
- Saving to database!, Validating..., Logging save...
- Logging save..., Validating..., Saving to database!
- Validating..., Logging save..., Saving to database!
- Only Saving to database!
Answer: Logging save..., Validating..., Saving to database!. Following the MRO, LoggingMixin runs first, then ValidationMixin, then BaseModel does the real work.
When is composition ("has a") generally preferred over inheritance ("is a")?
- When there is a clear is-a relationship
- Whenever you need polymorphism
- When behaviour belongs to a specific object and shouldn't leak into a hierarchy
- Never; inheritance is always better
Answer: When behaviour belongs to a specific object and shouldn't leak into a hierarchy. Composition suits has-a relationships where state/behaviour belongs to a contained object rather than a subtype.