Skip to content

mixture

Mixin classes for great objects !

Python versions Build Status Tests Status codecov

Documentation PyPI Downloads Downloads per week GitHub stars

Creating mixin classes is a quite elegant way to design reusable object-oriented code in python. Doing it right might be tricky as python provides many alternate ways. This library provides

  • an @apply_mixins decorator for those users wishing to avoid inheritance at all when mixing classes
  • (TODO) a few reusable mix-in class

work in progress

Installing

> pip install mixture

Usage

1. Mix-in basics

a- Defining

A mix-in class in python is typically a class :

  • without __init__ constructor (to avoid constructor inheritance hell in case of multiple inheritance),
  • providing a set of instance/static/class methods to provide some functionality. This functionality may be based on the existence of certain fields.
  • that may also include class attributes. This can be used to explicitly add a field to an object without defining an __init__ method, as we'll see below)
  • without parent classes, or where the parent classes are mix-in classes themselves

For example this is a very basic mix-in class without any requirement on instance attributes:

class BarkerMixin:
    def bark(self):
        print("barking loudly")

Thanks to pyfields, we can easily create mix-in classes that include fields definitions without defining a constructor:

from pyfields import field

class TweeterMixin:
    afraid = field(default=False, 
                   doc="Status of the tweeter. When this is `True`," 
                       "tweets will be less aggressive.")

    def tweet(self):
        how = "lightly" if self.afraid else "loudly"
        print("tweeting %s" % how)

See pyfields documentation for details.

Alternatives for class-level field definition

You can obviously use more advanced libraries such as attrs or dataclasses but be aware that by default they create an __init__ method for you. The intent here is to provide a "minimal viable product" to define class-level fields without creating __init__ methods.

b- Mixing

In python we can already use such mixin classes without additional framework, simply by inheriting from them thanks to python's multiple inheritance capabilities:

class MagicDuck(BarkerMixin, TweeterMixin):
    pass

Let's try it by creating a barking and tweeting duck:

>>> d = MagicDuck()
>>> d.bark()
barking loudly
>>> d.tweet()
tweeting loudly
>>> d.afraid = True
>>> d.tweet()
tweeting lightly

In addition, this library provides a way to apply mixin classes without inheritance. The author does not have any opinion on this alternative, it may be marginally faster as the MRO cost is not paid for accessing members, but this would have to be studied (if you're interested, please discuss it here).

from mixture import apply_mixins

@apply_mixins(BarkerMixin, TweeterMixin)
class MagicDuck:
    pass

in that case a special field is set on the class for reference, containing the list of all members that were created as the result of copying from mixins:

>>> MagicDuck.__from_mixins__
('tweet', 'afraid', 'bark')

and if the mixin is an Abstract Base Class, the decorated class is registered as a virtual subclass so that isinstance and issubclass still work as expected.

2. Handy Mix-in classes

TODO

Main features / benefits

  • optionally apply mix-ins without inheritance thanks to @apply_mixins
  • add features quickly to your classes thanks to the provided library of mixins

See Also

This library was inspired by:

Others

Do you like this library ? You might also like my other python libraries

Want to contribute ?

Details on the github page: https://github.com/smarie/python-mixture