[Python-Dev] python and super (original) (raw)

Ethan Furman ethan at stoneleaf.us
Fri Apr 29 23:53:56 CEST 2011


Ricardo Kirkner wrote:

I'll give you the example I came upon:

I have a TestCase class, which inherits from both Django's TestCase and from some custom TestCases that act as mixin classes. So I have something like class MyTestCase(TestCase, Mixin1, Mixin2): ... now django's TestCase class inherits from unittest2.TestCase, which we found was not calling super. Even if this is a bug and should be fixed in unittest2, this is an example where I, as a consumer of django, shouldn't have to be worried about how django's TestCase class is implemented.

I have to disagree -- anytime you are using somebody else's code you need to be aware of what it's supposed to do -- especially when playing with multiple inheritance.

This response to the decorator I wrote for this situation may be helpful:

Carl Banks wrote (on Python-List):

The problem is that he was doing mixins wrong. Way wrong.

Here is my advice on mixins:

Mixins should almost always be listed first in the bases. (The only exception is to work around a technicality. Otherwise mixins go first.)

If a mixin defines init, it should always accept self, *args and **kwargs (and no other arguments), and pass those on to super().init. Same deal with any other function that different sister classes might define in varied ways (such as call).

A mixin should not accept arguments in init. Instead, it should burden the derived class to accept arguments on its behalf, and set attributes before calling super().init, which the mixin can access.

If you insist on a mixin that accepts arguments in init, then it should should pop them off kwargs. Avoid using positional arguments, and never use named arguments. Always go through args and kwargs.

If mixins follow these rules, they'll be reasonably safe to use on a variety of classes. (Maybe even safe enough to use in Django classes.)

Ethan



More information about the Python-Dev mailing list