overriding base class

Carl Banks pavlovevidence at gmail.com
Fri Jun 29 23:23:07 EDT 2007


On Jun 29, 7:36 pm, alf <ask at me> wrote:
> Hi,
>
> I want to develop a following lib:
>
> lib space     user space
>
> A -> B -> | -> user_class
>
> however A and B are abstrac enough to have following:
>
> user_super_base_class -> | -> A -> B -> | -> user_class
>
> user space                  lib space      user spaca
>
> Any idea how to do that?


One possibility is to use multiple inheritance to get the same
effect.  This is easy in Python but wouldn't work in C++.  Note: it's
very important use new-style classes, however, so always inherit from
object or some other new-style class.

First, in the library space define A and B.  Notice that even though A
derives from object, it calls the "base" class's method.

class A(object):
    def method(self):
        print "calling A.method"
        super(A,self).method()

class B(A):
    def method(self):
        print "calling B.method"
        super(B,self).method()

In user space, declare the base class as so.  Note that super is not
called because this is the "real" base.

class SuperBase(object):
    def method(self):
        print "calling SuperBase.method"

Then, the user class.  We use multiple inheritance here, and put
SuperBase at the end.  The effect is the same as if A had been derived
from SuperBase.

class User(B,SuperBase):
    def method(self):
        print "calling User.method"
        super(User,self).method()


Calling this User().method() produces the following output:

 calling User.method
 calling B.method
 calling A.method
 calling SuperBase.method


Notice that A.method calls SuperBase.method, quite unintuitively for
someone not used to Python's MRO rules.  Basically, whenever you have
multiple bases, Python creates a consistent ordering of the bases,
called the Method Resolution Order (MRO), according to precedence.
You can exploit this to "insert" a super base class at the bottom.

You can see what the MRO of a class is with the __mro__ attribute.
For example, User.__mro__ is:

(<class '__main__.User'>,
 <class '__main__.B'>,
 <class '__main__.A'>,
 <class '__main__.SuperBase'>,
 <type 'object'>)

Even though A didn't derive directly from SuperBase, it acts as if it
had been, because it's right before SuperBase in the MRO.

Now that I've suggested that, I highly recommend you be sure you're
very acquainted with new-style objects and method resolution order
before attempting this.  You need extra care when using MI, even
though this use of it is rather tame.


Cark Banks




More information about the Python-list mailing list