Python Mixins
Carl Banks
pavlovevidence at gmail.com
Sat Sep 24 05:58:37 EDT 2011
On Thursday, September 22, 2011 2:14:39 PM UTC-7, Matt wrote:
[snip]
> class MyMixin(object):
> def one_thing(self):
> return "something cool"
>
> @mixin(MyMixin)
> class MyClass(object):
> pass
>
> x = MyClass()
> x.one_thing() == 'something cool'
> x.__class__.__bases__ == (object,)
>
> To me, this is much more concise. By looking at this I can tell what
> MyClass IS, who it's parents are and what else it can do. I'm very
> interested to know if there are others who feel as dirty as I do when
> using inheritance for mixins
Not me. Inheritance perfectly encompasses the mixin relationship, and because inheritance is so thoroughly ingrained in Python, it makes sense not to create a completely different mechanism to share behavior just for the case of mixins.
I know that, as someone who reads code, I would rather coders stick to well-known mechanisms than to create their own ad hoc mechanisms that don't actually add any new capability. Take your MyClass example above. If you had stuck to inheritance I could have seen what classes all the behavior was implemented by listing the __bases__. But since you used an ad hoc mechanism, now I have to track down where the hell that one_thing() method is coming from.
No mechanism is ever perfect, and Python's MI is very far from perfect, but sticking to well-known and understood methods is usually more important than whatever little improvement you can make. (And it is little; best as I can tell, your main objection is that mixins make it harder to see what the "main" parent is. I'd say that's a dubious justification to spring a new behavior-sharing mechanism on a reader.)
> or if there are other things that Python
> developers are doing to mix in functionality without using inheritance
> or if the general populous of the Python community disagrees with me
> and thinks that this is a perfectly valid use of inheritance.
I'd guess the majority just use inheritance, although I can't say I've seen enough code out there to gauge it.
But there is something else a lot of Pythonistas will do in many cases: just define regular functions. In your example, instead of defining one_thing() as a method of a mixin, define it as a function. Personally, I find that I almost never use mixins, though I have absolutely nothing against them and I use MI and metaclasses all the time. It's just that for most things I'd use a mixin for, I find that one or two regular functions work perfectly well.
Carl Banks
More information about the Python-list
mailing list