2

Suppose I have the following class structure:

class Mixin1(Base1):
    def get_data(self):
        # Gather some data in some way


class Mixin2(Base2):
    def get_data(self):
        # Gather some data in another way


class MyClass(Mixin1, Mixin2):
    def get_data(self):
        # Gather some data in yet another way.  Then...
        # Get Mixin2's version of get_data.  Then...
        # Get Mixin1's version of get_data.

An example case to provide some context is that Mixin1 is an authentication handler and Mixin2 is a login handler. The functionality in the parent classes will populate instance variables (say, error messages).

What would be the most Pythonic approach to calling the parent's get_data methods?

One approach to get this kind of information might be something like this:

original_class = self.__class__.__base__
parents = [base for base in original_class.__bases__]
for parent in parents:
    parent.get_data()

I don't see this as an unreasonable approach but if I have to start crawling into the meta I begin to wonder if there is a more Pythonic approach.

Any suggestions? Is it possible to use super() for this?

Rico
  • 5,692
  • 8
  • 46
  • 63
  • 4
    `super()` is precisely what you should be using, as it is intended to solve exactly this problem. – kindall May 22 '15 at 19:37
  • 2
    You should read [Super considered super](https://rhettinger.wordpress.com/2011/05/26/super-considered-super/) which explains exactly how to use super in a multiple inheritance scenario. – Daniel Roseman May 22 '15 at 19:42
  • 1
    @kindall How do you handle the case of choosing which parent's method to call using `super()`? What if you want to call them in a particular order? – Uyghur Lives Matter May 22 '15 at 20:11
  • If I read "Super considered super" properly, it would only call one super and mask the others. Rico wants to call both supers. – Robert Jacobs May 22 '15 at 20:17
  • @cpburnz: It follows the [C3 linearization](http://en.wikipedia.org/wiki/C3_linearization). In brief, you list the class you want called into first as your first superclass. – Kevin May 22 '15 at 20:18
  • 1
    From the documentation: "The second use case is to support cooperative multiple inheritance". Cooperative means all the classes in the class hierarchy are designed to work together. If `super` isn't called from all of them, they aren't designed properly. – chepner May 22 '15 at 21:04
  • The parent classes in this case do not inherit from anything and do not `super`. So, "Super considered super" did not address my question. I've read that many times - fantastic read! – Rico May 26 '15 at 15:34

1 Answers1

4
class MyClass(Mixin1, Mixin2):
    def get_data(self):
        # do local stuff
        data2 = Mixin2.get_data(self)
        data1 = Mixin1.get_data(self)

Also, this post seems to be related.

Another approach is to use containment instead of inheritance.

Community
  • 1
  • 1
Honza Osobne
  • 2,629
  • 1
  • 13
  • 9