Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > super() not a panacea?

Reply
Thread Tools

super() not a panacea?

 
 
Clarence Gardner
Guest
Posts: n/a
 
      02-17-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?"


 
Reply With Quote
 
 
 
 
Michele Simionato
Guest
Posts: n/a
 
      02-18-2004
"Clarence Gardner" <(E-Mail Removed)> wrote in message news:<(E-Mail Removed)> ...
> 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
 
Reply With Quote
 
 
 
 
Michele Simionato
Guest
Posts: n/a
 
      02-18-2004
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()
 
Reply With Quote
 
John Roth
Guest
Posts: n/a
 
      02-18-2004
"Clarence Gardner" <(E-Mail Removed)> wrote in message
news(E-Mail Removed).. .
>
> 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.


Have you reviewed the current method resolution order?

http://www.python.org/2.3/mro.html

I believe it was developed specifically to deal with this
problem.

Also, I'm firmly of the opinion that if you've got one of these
bizzare cases, you've got a design smell that should be dealt
with immediately, rather than expecting rational behavior from
language facilities.

"Rational," in this case, usually means "do what I need done
in this specific case, regardless of what anyone else thinks."

John Roth


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
To be not, or not to be not? Ruby Freak Ruby 2 09-23-2008 08:04 AM
Why not 'foo = not f' instead of 'foo = (not f or 1) and 0'? Kristian Domke Python 11 01-23-2008 07:27 PM
'' is not a valid name. Make sure that it does not include invalid characters or punctuation and that it is not too long. rote ASP .Net 2 01-23-2008 03:07 PM
Cisco 3640 3620 3600 not detecting, not enabling, not working: NM-2FE2W Taki Soho Cisco 0 09-22-2004 07:28 AM
maintaining control with cookies (not strictly an ASP or even server side question. But not not either) Stephanie Stowe ASP General 2 04-07-2004 04:23 PM



Advertisments