multiple inheritance

N

newseater

i don't know how to call methods of super classes when using multiple
inheritance. I've looked on the net but with no result :(

class a(object):
def foo(self):
print "a"

class b(object):
def foo(self):
print "a"

class c(a,b)
def foo(self):
super( ???? a).foo()
super( ???? b).foo()

r = c()
r.foo()
 
A

Andreas Kostyrka

I'm sure it's documented somewhere, but here we go :)

The correct usage is super(MyClass, self)

The idea is that super allows for cooperative calls. It uses MyClass to locate
what class "above" to call.

This way you can something like that:

class A(object):
def bar(self):
print "A"
#getattr(super(A, self),"bar", lambda : None)()

class B(object):
def bar(self):
print "B"
#getattr(super(B, self),"bar", lambda : None)()

class C(A,B):
def bar(self):
print "C"
getattr(super(C, self),"bar", lambda : None)()

print "-" * 20, "no super in A/B"
C().bar()

class A(object):
def bar(self):
print "A"
getattr(super(A, self),"bar", lambda : None)()

class B(object):
def bar(self):
print "B"
getattr(super(B, self),"bar", lambda : None)()

class C(A,B):
def bar(self):
print "C"
getattr(super(C, self),"bar", lambda : None)()

print "-" * 20, "protected getattr/super in A/B"

C().bar()

class base(object):
def bar(self):
print "base"

class A(base):
def bar(self):
print "A"
getattr(super(A, self), "bar", lambda : None)()

class B(base):
def bar(self):
print "B"
getattr(super(B, self), "bar", lambda : None)()

class C(A,B):
def bar(self):
print "C"
getattr(super(C, self), "bar", lambda : None)()

print "-" * 20, "base class without super call"
C().bar()

This produces:
-------------------- no super in A/B
C
A
-------------------- protected getattr/super in A/B
C
A
B
-------------------- base class without super call
C
A
B
base

Andreas
 
N

newseater

if I only use the super() construct it seems not to call B




class A(object):
def foo(self):
print "a"

class B(object):
def foo(self):
print "b"

class C(A,B):
def foo(self):
print "c"
super(C,self).foo()


c = C()

produces
c
a




oddly i can produce a "b" by using

super(A,self).foo()

i'm not sure why it isn't super(B,self).foo()
 
D

Duncan Booth

newseater said:
if I only use the super() construct it seems not to call B




class A(object):
def foo(self):
print "a"

class B(object):
def foo(self):
print "b"

class C(A,B):
def foo(self):
print "c"
super(C,self).foo()


c = C()

produces
c
a

That is because a single call to super only calls a single method from one
base class. Each call to super works out which is the next method that
should be called and calls it, but it is then up to that method to ensure
the call gets passed on along the chain.

The problem with super is that you need to be sure to terminate that
calling chain somehow. You can do what Andreas did, and use getattr to
check for the existence of the base class method, but that gets messy. I
find the easiest way is to define the interface in an abstract base class
which deliberately doesn't pass the call upwards:

class IFoo(object):
def foo(self):
pass

class A(IFoo):
def foo(self):
print "a"
super(A,self).foo()

class B(IFoo):
def foo(self):
print "b"
super(B,self).foo()

class C(A,B):
def foo(self):
print "c"
super(C,self).foo()


You can also ask a class the order in which its base classes are examine
for methods:
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class
'__main__.IFoo'>, <type 'object'>]

This is how super works, 'super(A, self)' when self is a C returns an
object which will look at self.__class__.mro(), which is the list above,
finds the class A, and then searches the remaining classes for matching
attributes (B, IFoo, then object). The same super call on an instance of A
gets a shorter list which doesn't include B as a possible target:
[<class '__main__.A'>, <class '__main__.IFoo'>, <type 'object'>]
 
N

newseater

how nice! is this due to a linearization taking place of A and B when
compiling C ? is this a 'feature' of the language or its actual
semantics to behave like this?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,219
Latest member
KristieKoh

Latest Threads

Top