A Super Solution

Python provides a class attribute __mro__ for each type, and a type called super. The __mro__ attribute is a tuple containing the type itself and all of its supertypes in a specific order. The type super is used in place of the find_out_whos_next() method but is capable of more.

Example 2.5. One super technique

class B(A): 1
    def do_your_stuff(self):
        super(B, self).do_your_stuff() 2
        # do stuff with self for B


2

The super() call returns a super object. It finds the next type after B in self.__class__.__mro__. Attributes accessed on the super object are searched on the next type and returned. Descriptors are resolved. What this means is accessing a method (as above) returns a bound method (note the do_your_stuff() call does not pass self). When using super() the first parameter should always be the same as the class in which it is being used (1).

If we're using a class method, we don't have an instance to call super with. Fortunately for us, super works even with a type as the second argument. Observe that above, super uses self only to get at self.__class__. The type can be passed directly to super as shown below.

Example 2.6. Using super with a class method

class B(A):
    def do_something(cls):
        super(B, cls).do_something()

    do_something = classmethod(do_something)

There is a different way to use super as well.

Example 2.7. Another super technique

class B(A):

    def do_your_stuff(self):
        self.__super.do_your_stuff()
        # do stuff with self for B

B._B__super = super(B) 1

When created with only a type, the super instance behaves like a descriptor. This means (if d is an instance of D) that super(B).__get__(d) returns the same thing as super(B,d). In 1 above, we munge an attribute name, similar to what Python does for names starting with double underscore inside the class. So this is accessible as self.__super within the body of the class. If we didn't use a class specific attribute name, accessing the attribute through the instance self might return an object defined in a subtype.

While using super we typically use only one super call in one method even if the class has multiple bases. Also, it is a good programming practice to use super instead of calling methods directly on a base class.

A possible pitfall appears if do_your_stuff() accepts different arguments for C and A. This is because, if we use super in B to call do_your_stuff() on the next class, we don't know if it is going to be called on A or C. If this scenario is unavoidable, a case specific solution might be required.