471,309 Members | 1,436 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,309 software developers and data experts.

super() not a panacea?


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?"
Jul 18 '05 #1
2 1556
"Clarence Gardner" <cl******@netlojix.net> wrote in message news:<pa****************************@netlojix.net> ...
The super object is considered a solution to the "diamond problem".
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.


The solution I see is to introduce a placeholder base class Y
with a dummy "m" method on top of the hierarchy:

class Y(object):
def m(self):
pass

class A(Y):
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(Y):
def m(self):
print ' Z'

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

X().m()

D().m()
print X.mro()
print D.mro()

This is the easy solution. If you don't like it, let me know and I
will show you other possibilities.

Michele Simionato
Jul 18 '05 #2
Here is another solution that you will probably like more, since it does
not require to change the hierarchy. The trick is to use a custom "super"
which ignores attribute errors:

class mysuper(super):
def __getattribute__(self,name):
try:
return super.__getattribute__(self,name)
except AttributeError: # returns a do-nothing method
return lambda *args, **kw: None

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

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

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

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

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

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

X().m()

D().m()
print X.mro()
print D.mro()
Jul 18 '05 #3

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

4 posts views Thread by Kerim Borchaev | last post: by
11 posts views Thread by Nicolas Lehuen | last post: by
reply views Thread by Michele Simionato | last post: by
reply views Thread by Delaney, Timothy C (Timothy) | last post: by
6 posts views Thread by Steven Bethard | last post: by
7 posts views Thread by Kent Johnson | last post: by
7 posts views Thread by Pupeno | last post: by
9 posts views Thread by Mike Krell | last post: by
4 posts views Thread by ddtl | last post: by
reply views Thread by rosydwin | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.