[Python-ideas] mixins as decorators vs inheritance [was: Automatic comparisons by default]

Mike Graham mikegraham at gmail.com
Fri Mar 18 14:58:38 CET 2011

On Fri, Mar 18, 2011 at 8:59 AM, Jim Jewett <jimjjewett at gmail.com> wrote:
> On Thu, Mar 17, 2011 at 9:48 AM, Mike Graham <mikegraham at gmail.com> wrote:
>> On Wed, Mar 16, 2011 at 5:48 PM, Masklinn <masklinn at masklinn.net> wrote:
>>> (also, since I apparently completely missed this,
>>> what was the rationale of making it a class
>>> decorator rather than, say, a mixin?)
>> Perhaps the better question is "Why do we ever
>> do mixins through inheritance?"
> That is a good question, and I was tempted to switch,
> until I realized that there are some good answers...
> (a)  So we can do an isinstance check
> (b)  So we can more easily override parts of the mixin
> -jJ

(a) is a misfeature. isinstance checks are bad: they make your code
less flexible – in Python the actual type of an object isn't something
we treat as semantic data. This is *especially* the case with mixins,
which are just a convenient thing for code reuse, not some meaningful

To take the initial example, if functools.total_ordering was
implemented with the inheritance style, checking isinstance(foo,
TotallyOrdered) would make zero sense, as
supporting-all-ordering-operations isn't a meaningful abstract
category. It would also exclude all those classes that already exist
and implement all six operators.*

(b) is more compelling. We would have to write code to force only
mixing in the methods we want manually and allowing overriding
(probably automatically) if we wanted to use decorator-based-mixins.
We could write this code just once as a mixin library (it's actually
quite trivial).

I actually see this as better for overriding than
inheritance-based-mixins in some ways. For example, if I wanted to
write my own foo overriding SomeMixin.foo, I almost certainly wouldn't
call SomeMixin.foo: I don't want it. But that's totally against the
rules! I show for myself that I'm not really doing inheritance, and I
might be breaking super for someone else down the line.


*Of course, here I am ignoring the possibility that TotallyOrdered**
is implemented as an abstract base class and all the stdlib is
registered with it appropriately. This is because I don't think that
would be the right thing to do – TotallyOrdered isn't a meaningful
abstract type. More fundamentally, I also worry that Python ABCs'
pairing of interface and default implementation breaks down in some
common cases.

**My only major reservation in opposing a TotallyOrdered class is that
I absolutely love the name.

More information about the Python-ideas mailing list