Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Python 2.3.3 super() behaviour

Reply
Thread Tools

Python 2.3.3 super() behaviour

 
 
David Fraser
Guest
Posts: n/a
 
      04-22-2004
Hi Nicolas

Another related idea:
Use template functions when you have enough control over the objects:

def A(base=object):
class A(base):
def __init__(self):
print "A"
super(A, self).__init__()
return A

def B(base=object):
class B(base):
def __init__(self):
print "B"
super(B, self).__init__()
return B

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

C()

This is a bit different to multiple inheritance, but can have nice
effects...

David

Nicolas Lehuen wrote:
> Ah, so there *is* more than one way to do it, then ?
>
> What the example shows is that super(...).__init__ does make one call to
> each superclass' __init__, provided that those superclasses play nicely and
> use super() themselves (as Peter wrote). If one of the superclasses does not
> use super(), the 'magical' iteration over parent methods is interrupted,
> hence the need to put those bad guys at the end of the superclasses list in
> the class declaration.
>
> But you're right, David, the simplest way to get what I want is to
> explicitely call the superclasses' __init__. However, this would mean that
> super() is not as useful as it seems. I'd rather find a way to *always* use
> super() than have special cases for certain inheritance trees. In other
> words, I'd rather have only one way to do it .
>
> Regards,
> Nicolas
>
> "David Fraser" <(E-Mail Removed)> a écrit dans le message de
> news:c65j4o$3me$(E-Mail Removed)...
>
>>super is not going to be helpful here, so why not call the X.__init__
>>functions explicitly?
>>Since you *need* multiple __init__ calls from the multiply-inherited
>>class, super isn't going to work...
>>
>>Nicolas Lehuen wrote:
>>
>>>The only problem I have is that I want to build a multiple inheritance
>>>involving an object which does not cooperate, namely :
>>>
>>>class T(object):
>>> def __init__(self):
>>> super(T,self).__init__()
>>>
>>>class TL(list,object):
>>> def __init__(self)
>>> super(TL,self).__init__()
>>>
>>>In this case, T.__init__ is not called, because list.__init__ does not

>
> use
>
>>>super(). The only clean way to proceed is to change the inheritance

>
> order :
>
>>>TL(T,list). This way, both constructors are called.
>>>
>>>Here is another example which exhibits the behaviour :
>>>
>>>class A(object):
>>> def __init__(self):
>>> super(A,self).__init__()
>>> print 'A'
>>>
>>>class B(object):
>>> def __init__(self):
>>> print 'B'
>>>
>>>class C(B,A):
>>> def __init__(self):
>>> super(C,self).__init__()
>>> print 'C'
>>>
>>>class D(A,B):
>>> def __init__(self):
>>> super(D,self).__init__()
>>> print 'D'
>>>
>>>
>>>
>>>>>>C()
>>>
>>>B
>>>C
>>><__main__.C object at 0x008F3D70>
>>>
>>>>>>D()
>>>
>>>B
>>>A
>>>D
>>><__main__.D object at 0x008F39F0>
>>>
>>>The problem is that if you go further down the inheritance, the

>
> behaviour is
>
>>>even more complicated :
>>>
>>>class E(object):
>>> def __init__(self):
>>> super(E,self).__init__()
>>> print 'E'
>>>
>>>class F(C,E):
>>> def __init__(self):
>>> super(F,self).__init__()
>>> print 'F'
>>>
>>>class G(D,E):
>>> def __init__(self):
>>> super(G,self).__init__()
>>> print 'G'
>>>
>>>
>>>
>>>>>>F()
>>>
>>>B
>>>C
>>>F
>>><__main__.F object at 0x008F3D70>
>>>
>>>>>>G()
>>>
>>>B
>>>A
>>>D
>>>G
>>><__main__.G object at 0x008F3EF0>
>>>
>>>class H(E,C):
>>> def __init__(self):
>>> super(H,self).__init__()
>>> print 'H'
>>>
>>>class I(E,D):
>>> def __init__(self):
>>> super(I,self).__init__()
>>> print 'I'
>>>
>>>
>>>
>>>>>>H()
>>>
>>>B
>>>C
>>>E
>>>H
>>><__main__.H object at 0x008F3E30>
>>>
>>>>>>I()
>>>
>>>B
>>>A
>>>D
>>>E
>>>I
>>><__main__.I object at 0x008F3FD0>
>>>
>>>So the conclusion is : never do that . Another more constructive
>>>conclusion would be : always put the most cooperative classes first in

>
> the
>
>>>inheritance declaration, provided that it doesn't interfere with your

>
> needs.
>
>>>A class which has an uncooperative ancestor is less cooperative than a

>
> class
>
>>>which has only cooperative ancestors.
>>>
>>>Regards,
>>>Nicolas
>>>
>>>"Nicolas Lehuen" <(E-Mail Removed)> a écrit dans le

>
> message
>
>>>de news:40864674$0$24834$(E-Mail Removed)...
>>>
>>>
>>>>OK, I get it now, thanks.
>>>>
>>>>super() method calls should only be used for method involved in
>>>>diamond-shaped inheritance. This is logical since in this case the base
>>>>classe (from which the diamond-shaped inheritance starts) defines the
>>>>interface of the method.
>>>>
>>>>This solves another question I was asking myself about super() : "how

>
> can
>
>>>it
>>>
>>>
>>>>work when the method signature differ between B and C ?". Answer : the
>>>>method signature should not change because polymorphic calls would be
>>>>greatly endangered. The base class defines the signature of the method
>>>
>>>which
>>>
>>>
>>>>must be followed by all its children, this way super() can work

>
> properly.
>
>>>>The base method signature is not enforced by Python, of course, but

>
> you'd
>
>>>>better respect it unless you get weird result in polymorphic calls.
>>>>
>>>>Regards,
>>>>Nicolas
>>>>
>>>>"Peter Otten" <(E-Mail Removed)> a écrit dans le message de
>>>>news:c65fbo$1q4$05$(E-Mail Removed)-online.com...
>>>>
>>>>
>>>>>Nicolas Lehuen wrote:
>>>>>
>>>>>
>>>>>
>>>>>>Hi,
>>>>>>
>>>>>>I hope this is not a FAQ, but I have trouble understanding the
>>>
>>>behaviour
>>>
>>>
>>>>>>of the super() built-in function. I've read the excellent book 'Python
>>>>
>>>>in
>>>>
>>>>
>>>>>>a Nutshell' which explains this built-in function on pages 89-90.
>>>
>>>Based
>>>
>>>
>>>>on
>>>>
>>>>
>>>>>>the example on page 90, I wrote this test code :
>>>>>>
>>>>>>class A(object):
>>>>>> def test(self):
>>>>>> print 'A'
>>>>>>
>>>>>>class B(object):
>>>>>> def test(self):
>>>>>> print 'B'
>>>>>>
>>>>>>class C(A,B):
>>>>>> def test(self):
>>>>>> super(C,self).test()
>>>>>> print 'C'
>>>>>>
>>>>>>print C.__mro__
>>>>>>c=C()
>>>>>>c.test()
>>>>>>
>>>>>>The output is :
>>>>>>(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>,
>>>
>>><type
>>>
>>>
>>>>>>'object'>)
>>>>>>A
>>>>>>C
>>>>>>
>>>>>>Whereas I was expecting :
>>>>>>(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>,
>>>
>>><type
>>>
>>>
>>>>>>'object'>)
>>>>>>A
>>>>>>B
>>>>>>C
>>>>>>
>>>>>>Was I wrong to expect this (based on what I've read ?)
>>>>>
>>>>>As soon as a test() method without the super(...).test() is reached, no
>>>>>further test methods will be invoked. Only the first in the list of

>
> base
>
>>>>>classes will be invoked. If I'm getting it right you have to do
>>>
>>>something
>>>
>>>
>>>>>like:
>>>>>
>>>>>class Base(object):
>>>>> def test(self):
>>>>> print "base"
>>>>>
>>>>>class D1(Base):
>>>>> def test(self):
>>>>> super(D1, self).test()
>>>>> print "derived 1"
>>>>>
>>>>>class D2(Base):
>>>>> def test(self):
>>>>> super(D2, self).test()
>>>>> print "derived 2"
>>>>>
>>>>>class All(D1, D2):
>>>>> pass
>>>>>
>>>>>All().test()
>>>>>
>>>>>Here all cooperating methods have a super() call, and the base class
>>>
>>>acts
>>>
>>>
>>>>as
>>>>
>>>>
>>>>>a showstopper to prevent that Python tries to invoke the non-existent
>>>>>object.test().
>>>>>
>>>>>Peter
>>>>>
>>>>>
>>>>>
>>>>
>>>>
>>>

>
>

 
Reply With Quote
 
 
 
 
Nicolas Lehuen
Guest
Posts: n/a
 
      04-22-2004
Duh, so it was a FAQ...

What's interesting in your post is the fact that super is in fact a class
(not a builtin function), and that you can inherit from it to get the
expected behaviour :

http://groups.google.it/groups?hl=it...mp.lang.python

Maybe this should be the default behaviour ?

Regards,
Nicolas

"Michele Simionato" <(E-Mail Removed)> a écrit dans le message de
news:(E-Mail Removed) om...
> "Nicolas Lehuen" <(E-Mail Removed)> wrote in message

news:<40863bd7$0$25528$(E-Mail Removed)>.. .
> > Hi,
> >
> > I hope this is not a FAQ, but I have trouble understanding the behaviour

of
> > the super() built-in function.

>
> Maybe this thread on super will interest you:
>
>

http://groups.google.it/groups?hl=it....lang.python.*
>
>
> Michele Simionato



 
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
debugger behaviour different to execution behaviour Andy Chambers Java 1 05-14-2007 09:51 AM
Documentation bug: Python console behaviour changed Kay Schluehr Python 6 07-19-2005 10:50 PM
Unexpected mod-python behaviour. Simon Wittber Python 1 02-06-2004 06:45 PM
Unexpected python behaviour Richard Philips Python 2 11-28-2003 03:14 PM
Strange Python COM behaviour a_bogdan_marinescu Python 1 11-16-2003 02:12 AM



Advertisments