Mixins in Python

A mixin is a class which is used as an additional base class and adds the implementation of a feature, mixing it into the derived class. This allows derived classes to be assembled from components, adding only those features they require.

A good example of mixins is Werkzeug’s Request/Response Wrapper Mixins.

A typical Werkzeug application starts by taking the WSGI environment and constructs a Request object out of it:

def application(environ, start_response):
    request = Request(environ)

The Request class is often a user-defined class derived from werkzeug.wrappers.BaseRequest. This is a bare-bones class that does not provide features like E-Tags and cache control. In order for implementors to be able to add those features to their class, Werkzeug provides a number of mixins for HTTP features:

  • AcceptMixin for accept header parsing
  • ETagRequestMixin for etag and cache control handling
  • UserAgentMixin for user agent introspection
  • AuthorizationMixin for http auth handling
  • CommonRequestDescriptorsMixin for common headers

Implementors add one or more of these classes to the derivation list of their class to mix in the features they want:

from werkzeug.wrappers import AcceptMixin, BaseRequest

class Request(BaseRequest, AcceptMixin):
    pass

The implementor can then access attributes of the AcceptMixin from the Request class

mimetypes = request.accept_mimetypes

If this wasn’t done using mixins, it would be necessary to explicitly aggregate an object to implement the Accept headers when the Request object was constructed, something like this:

class Request(BaseRequest):
    def __init__(self):
        self.acceptor = AcceptComponent() # Not a real class

And then it would need to be accessed indirectly, something like this:

mimetypes = request.acceptor.accept_mimetypes # Not real code

So you can see that a mixin has simplified the construction and use of the class.

Two properties of mixins are:

  • By their very nature mixins are useless on their own – their sole purpose is to be mixed into other classes
  • They are tightly coupled to the classes into which they can be mixed in, since they must have intimate knowledge of them in order to be able to do anything useful