In "Programming Python", Mark Lutz mentions "mixins". I'm from a C/C++/C# background and I have not heard the term before. What is a mixin?
Reading between the lines of this example (which I've linked to because it's quite long), I'm presuming it's a case of using multiple inheritance to extend a class as opposed to 'proper' subclassing. Is this right?
Why would I want to do that rather than put the new functionality into a subclass? For that matter, why would a mixin/multiple inheritance approach be better than using composition?
What separates a mixin from multiple inheritance? Is it just a matter of semantics?
Maybe an example from ruby can help:
You can include the mixin
Comparable
and define one function"<=>(other)"
, the mixin provides all those functions:It does this by invoking
<=>(other)
and giving back the right result."instance <=> other"
returns 0 if both objects are equal, less than 0 ifinstance
is bigger thanother
and more than 0 ifother
is bigger.It's not a Python example but in the D programing language the term
mixin
is used to refer to a construct used much the same way; adding a pile of stuff to a class.In D (which by the way doesn't do MI) this is done by inserting a template (think syntactically aware and safe macros and you will be close) into a scope. This allows for a single line of code in a class, struct, function, module or whatever to expand to any number of declarations.
I'd advise against mix-ins in new Python code, if you can find any other way around it (such as composition-instead-of-inheritance, or just monkey-patching methods into your own classes) that isn't much more effort.
In old-style classes you could use mix-ins as a way of grabbing a few methods from another class. But in the new-style world everything, even the mix-in, inherits from
object
. That means that any use of multiple inheritance naturally introduces MRO issues.There are ways to make multiple-inheritance MRO work in Python, most notably the super() function, but it means you have to do your whole class hierarchy using super(), and it's considerably more difficult to understand the flow of control.
I think there have been some good explanations here but I wanted to provide another perspective.
In Scala, you can do mixins as has been described here but what is very interesting is that the mixins are actually 'fused' together to create a new kind of class to inherit from. In essence, you do not inherit from multiple classes/mixins, but rather, generate a new kind of class with all the properties of the mixin to inherit from. This makes sense since Scala is based on the JVM where multiple-inheritance is not currently supported (as of Java 8). This mixin class type, by the way, is a special type called a Trait in Scala.
It's hinted at in the way a class is defined: class NewClass extends FirstMixin with SecondMixin with ThirdMixin ...
I'm not sure if the CPython interpreter does the same (mixin class-composition) but I wouldn't be surprised. Also, coming from a C++ background, I would not call an ABC or 'interface' equivalent to a mixin -- it's a similar concept but divergent in use and implementation.
A mixin is a special kind of multiple inheritance. There are two main situations where mixins are used:
For an example of number one, consider werkzeug's request and response system. I can make a plain old request object by saying:
If I want to add accept header support, I would make that
If I wanted to make a request object that supports accept headers, etags, authentication, and user agent support, I could do this:
The difference is subtle, but in the above examples, the mixin classes weren't made to stand on their own. In more traditional multiple inheritance, the
AuthenticationMixin
(for example) would probably be something more likeAuthenticator
. That is, the class would probably be designed to stand on its own.This answer aims to explain mixins with examples that are:
self-contained: short, with no need to know any libraries to understand the example.
in Python, not in other languages.
It is understandable that there were examples from other languages such as Ruby since the term is much more common in those languages, but this is a Python thread.
It shall also consider the controversial question:
Definitions
I have yet to see a citation from an "authoritative" source clearly saying what is a mixin in Python.
I have seen 2 possible definitions of a mixin (if they are to be considered as different from other similar concepts such as abstract base classes), and people don't entirely agree on which one is correct.
The consensus may vary between different languages.
Definition 1: no multiple inheritance
A mixin is a class such that some method of the class uses a method which is not defined in the class.
Therefore the class is not meant to be instantiated, but rather serve as a base class. Otherwise the instance would have methods that cannot be called without raising an exception.
A constraint which some sources add is that the class may not contain data, only methods, but I don't see why this is necessary. In practice however, many useful mixins don't have any data, and base classes without data are simpler to use.
A classic example is the implementation of all comparison operators from only
<=
and==
:This particular example could have been achieved via the
functools.total_ordering()
decorator, but the game here was to reinvent the wheel:Definition 2: multiple inheritance
A mixin is a design pattern in which some method of a base class uses a method it does not define, and that method is meant to be implemented by another base class, not by the derived like in Definition 1.
The term mixin class refers to base classes which are intended to be used in that design pattern (TODO those that use the method, or those that implement it?)
It is not easy to decide if a given class is a mixin or not: the method could be just implemented on the derived class, in which case we're back to Definition 1. You have to consider the author's intentions.
This pattern is interesting because it is possible to recombine functionalities with different choices of base classes:
Authoritative Python occurrences
At the official documentatiton for collections.abc the documentation explicitly uses the term Mixin Methods.
It states that if a class:
__next__
Iterator
then the class gets an
__iter__
mixin method for free.Therefore at least on this point of the documentation, mixin does not not require multiple inheritance, and is coherent with Definition 1.
The documentation could of course be contradictory at different points, and other important Python libraries might be using the other definition in their documentation.
This page also uses the term
Set mixin
, which clearly suggests that classes likeSet
andIterator
can be called Mixin classes.In other languages
Ruby: Clearly does not require multiple inheritance for mixin, as mentioned in major reference books such as Programming Ruby and The Ruby programming Language
C++: A method that is not implemented is a pure virtual method.
Definition 1 coincides with the definition of an abstract class (a class that has a pure virtual method). That class cannot be instantiated.
Definition 2 is possible with virtual inheritance: Multiple Inheritance from two derived classes