super, apply, or __init__ when subclassing?

E

exhuma.twn

This is something that keeps confusing me. If you read examples of
code on the web, you keep on seeing these three calls (super, apply
and __init__) to reference the super-class. This looks to me as it is
somehow personal preference. But this would conflict with the "There
one way to do it" mind-set.

So, knowing that in python there is one thing to do something, these
three different calls must *do* domething different. But what exactly
*is* the difference?

------------ Exampel 1: -----------------------------

class B(A):
def __init__(self, *args):
A.__init__(self, args)

------------ Exampel 2: -----------------------------

class B(A):
def __init__(self, *args):
apply( A.__init__, (self,) + args)

------------ Exampel 3: -----------------------------

class B(A):
def __init__(self, *args):
super(A,self).__init__(*args)
 
B

Ben Finney

exhuma.twn said:
This is something that keeps confusing me. If you read examples of
code on the web, you keep on seeing these three calls (super, apply
and __init__) to reference the super-class. This looks to me as it is
somehow personal preference. But this would conflict with the "There
one way to do it" mind-set.

So, knowing that in python there is one thing to do something, these
three different calls must *do* domething different. But what exactly
*is* the difference?

------------ Exampel 1: -----------------------------

class B(A):
def __init__(self, *args):
A.__init__(self, args)

------------ Exampel 2: -----------------------------

class B(A):
def __init__(self, *args):
apply( A.__init__, (self,) + args)

------------ Exampel 3: -----------------------------

class B(A):
def __init__(self, *args):
super(A,self).__init__(*args)

Note that your examples 1 and 3 aren't different *calls*. They are
different ways of *getting at* the same class: either name it
explicitly (as in example 1) or use 'super' to get it for you.

Also, example 3 should instead call 'super(B, self).__init__'. If
you're going to go to the bother of actually *specifying* the class
'A', it's silly to call 'super' to get at it *again*.


The broader picture: I think you're right that this is ridiculously
difficult in Python. The community elders would have us use 'super' to
get at our inherited '__init__', but that doesn't work very well
<URL:http://fuhm.org/super-harmful/> so most people use your example
1.
 
D

Duncan Booth

exhuma.twn said:
So, knowing that in python there is one thing to do something, these
three different calls must *do* domething different. But what exactly
*is* the difference?

------------ Exampel 1: -----------------------------

class B(A):
def __init__(self, *args):
A.__init__(self, args)

------------ Exampel 2: -----------------------------

class B(A):
def __init__(self, *args):
apply( A.__init__, (self,) + args)

------------ Exampel 3: -----------------------------

class B(A):
def __init__(self, *args):
super(A,self).__init__(*args)

Yes, they are all different.

The first one calls B's immediate base class but packs all of the
arguments together into a single tuple. Probably not what you meant.

The second one passes B's positional arguments to its immediate base
class without messing them up but uses a deprecated function to do it.
You should use "A.__init__(self, *args)" instead unless you are
concerned about multiple inheritance.

The third one skips over the __init__ method in the immediate base class
and calls the __init__ method in whatever class follows A in the MRO
instead. Probably not what you meant either.
 
B

Bruno Desthuilliers

exhuma.twn a écrit :
This is something that keeps confusing me. If you read examples of
code on the web, you keep on seeing these three calls (super, apply
and __init__) to reference the super-class. This looks to me as it is
somehow personal preference. But this would conflict with the "There
one way to do it" mind-set.

apply is deprecated. Chances are that code using it is somewhat old.
super came with the new object model in Python 2.2.1 (IIRC), and is only
useful for some corner cases involving multiple inheritence . Directly
calling the superclass's method (__init__ or whatever) is the canonical
way in the most common cases.

And BTW, the sentence is "there *should* be one - and *preferably* only
one - *obvious* way to do it" (emphasis is mine). In this case, there's
_at least_ one way do to do it, and only one (direct call) is really
obvious IMHO !-)
So, knowing that in python there is one thing to do something, these
three different calls must *do* domething different.

Indeed. But mostly because you managed to get 2 examples wrong !-)
But what exactly
*is* the difference?

------------ Exampel 1: -----------------------------

class B(A):
def __init__(self, *args):
A.__init__(self, args)

You want:

class B(A):
def __init__(self, *args):
A.__init__(self, *args)

------------ Exampel 2: -----------------------------

class B(A):
def __init__(self, *args):
apply( A.__init__, (self,) + args)

is the same as the previous, using the deprecated apply function.
------------ Exampel 3: -----------------------------

class B(A):
def __init__(self, *args):
super(A,self).__init__(*args)

You want:

class B(A):
def __init__(self, *args):
super(B,self).__init__(*args)
 
G

Gabriel Genellina

This is something that keeps confusing me. If you read examples of
code on the web, you keep on seeing these three calls (super, apply
and __init__) to reference the super-class. This looks to me as it is
somehow personal preference. But this would conflict with the "There
one way to do it" mind-set.

So, knowing that in python there is one thing to do something, these
three different calls must *do* domething different. But what exactly
*is* the difference?

There are a few typos in your examples. If you write them this way:
------------ Exampel 1: -----------------------------

class B(A):
def __init__(self, *args):
A.__init__(self, *args)

------------ Exampel 2: -----------------------------

class B(A):
def __init__(self, *args):
apply( A.__init__, (self,) + args)

------------ Exampel 3: -----------------------------

class B(A):
def __init__(self, *args):
super(B,self).__init__(*args)

then 2 is exactly the same as 1 but using a deprecated function. And 3 is
the same as 1 only when there is single inheritance involved (and you are
using new-style classes). But see the thread "super() doesn't get
superclass"
 
E

exhuma.twn

exhuma.twn a écrit :


apply is deprecated. Chances are that code using it is somewhat old.
super came with the new object model in Python 2.2.1 (IIRC), and is only
useful for some corner cases involving multiple inheritence . Directly
calling the superclass's method (__init__ or whatever) is the canonical
way in the most common cases.

And BTW, the sentence is "there *should* be one - and *preferably* only
one - *obvious* way to do it" (emphasis is mine). In this case, there's
_at least_ one way do to do it, and only one (direct call) is really
obvious IMHO !-)


Indeed. But mostly because you managed to get 2 examples wrong !-)




You want:

class B(A):
def __init__(self, *args):
A.__init__(self, *args)

Ah.. this was a typo in my original post. Oops ;)
is the same as the previous, using the deprecated apply function.



You want:

class B(A):
def __init__(self, *args):
super(B,self).__init__(*args)

Hmmm... and suddenly it all makes sense! Great!

Thanks all for clarifying this to a Java-Convert ;)
 
E

exhuma.twn

There are a few typos in your examples. If you write them this way:

Example 3 was not really a typo on my side. While I was browsing
around for python, I saw this in a code-fragment. So I thought this
was the way to do it. Even though I thought "super(A..." does not make
sense in a "semantic" way. Instead of just accepting this as a fact I
probably should have trusted my gut-feeling and investigate.

Nonetheless the posts (and explanations) here were really helpful for
me to understand what's happening under the hood. But seeing these
three variants of doing (nearly) the same was an itch I finally
decided to scratch. So far I blindly used "Example 1" as it seemed to
work for me.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top