super() not a panacea?

Clarence Gardner clarence at netlojix.net
Tue Feb 17 19:59:19 CET 2004


The super object is considered a solution to the "diamond problem".
However, it generally requires that the ultimate base class know that it
is last in the method resolution order, and hence it should not itself
use super (as well as supplying the ultimate implementation of an
overridden method.)

However, a problem comes up if that ultimate base class is also the base
class for another which inherits from it and another independent base
class also providing that method. This results in a situation where the
first base class is now required to use super in order to propogate the
call chain over to the new classes, in the case of the object being an
instance of the newly-added subclass, but still must not use super in
the case of the object being an instance of the original (bottom of
diamond) class.

So, are we asking too much of super? Is there any resolution to this
problem? The only one we can see is that a super object somehow effect a
no-op when the search for a method ends with the "object" class (and
"object", of course, doesn't implement the sought method). This seems
yucky, though.


print '    ',r'''Typical diamond using super.
  A
 / \
B   C
 \ /
  D
'''

class A(object):
    def m(self):
        print '   A'

class B(A):
    def m(self):
        super(B, self).m()
        print '   B'

class C(A):
    def m(self):
        super(C, self).m()
        print '   C'

class D(B,C):
    def m(self):
        super(D, self).m()
        print '   D'

print '''create D instance and call m'''

D().m()

print r'''A C B D, looks good.  Now introduce classes Z & X
    A      Z
   /|\    /
  / | \  /
 /  |  \/
B   C   X
 \ /
  D
'''

class Z(object):
    def m(self):
        print '   Z'

class X(A, Z):
    def m(self):
        super(X, self).m()
        print '   X'

print '''create X instance and call m'''

X().m()

print '''"A X", Oh-oh, that is not right.  Z.m was not called.
That is because A is not calling super.
Change class A to call super.'''

class A(object):
    def m(self):
        super(A, self).m()
        print '   A'

class B(A):
    def m(self):
        super(B, self).m()
        print '   B'

class C(A):
    def m(self):
        super(C, self).m()
        print '   C'

class D(B,C):
    def m(self):
        super(D, self).m()
        print '   D'

class Z(object):
    def m(self):
        print '   Z'

class X(A, Z):
    def m(self):
        super(X, self).m()
        print '   X'

X().m()

print '"Z A X", That is much better.'
print 'Now, make sure D still works as before.'

try:
    D().m()
except AttributeError, e:
    print '   Error:', e
    print '    ',"super object has no attribute 'm'!, now what?"





More information about the Python-list mailing list