newseater wrote: > 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() >>> A().foo() a >>> B().foo() b >>> C().foo() c a b >>> You can also ask a class the order in which its base classes are examine for methods: >>> C.mro() [<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: >>> A.mro() [<class '__main__.A'>, <class '__main__.IFoo'>, <type 'object'>] -- http://mail.python.org/mailman/listinfo/python-list