super, apply, or __init__ when subclassing?

Discussion in 'Python' started by exhuma.twn, Sep 18, 2007.

  1. exhuma.twn

    exhuma.twn Guest

    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)
     
    exhuma.twn, Sep 18, 2007
    #1
    1. Advertising

  2. exhuma.twn

    Ben Finney Guest

    "exhuma.twn" <> writes:

    > 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.

    --
    \ "The most merciful thing in the world... is the inability of |
    `\ the human mind to correlate all its contents." -- Howard |
    _o__) Philips Lovecraft |
    Ben Finney
     
    Ben Finney, Sep 18, 2007
    #2
    1. Advertising

  3. exhuma.twn

    Duncan Booth Guest

    "exhuma.twn" <> wrote:

    > 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.
     
    Duncan Booth, Sep 18, 2007
    #3
  4. 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)
     
    Bruno Desthuilliers, Sep 18, 2007
    #4
  5. En Tue, 18 Sep 2007 04:33:11 -0300, exhuma.twn <> escribi�:

    > 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"

    --
    Gabriel Genellina
     
    Gabriel Genellina, Sep 18, 2007
    #5
  6. exhuma.twn

    exhuma.twn Guest

    On Sep 18, 2:45 pm, Bruno Desthuilliers <bruno.
    > wrote:
    > 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)


    Ah.. this was a typo in my original post. Oops ;)

    >
    > > ------------ 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)


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

    Thanks all for clarifying this to a Java-Convert ;)
     
    exhuma.twn, Sep 18, 2007
    #6
  7. exhuma.twn

    exhuma.twn Guest

    On Sep 18, 2:50 pm, "Gabriel Genellina" <>
    wrote:
    > En Tue, 18 Sep 2007 04:33:11 -0300, exhuma.twn <> escribi?:
    >
    > > 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:
    >


    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.

    >
    >
    > > ------------ 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"
    >
    > --
    > Gabriel Genellina
     
    exhuma.twn, Sep 18, 2007
    #7
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Guest

    super.super.super how?

    Guest, Feb 19, 2005, in forum: Java
    Replies:
    24
    Views:
    10,792
    Darryl Pierce
    Feb 24, 2005
  2. Jan Burgy
    Replies:
    4
    Views:
    448
    Peter Otten
    Apr 3, 2004
  3. Steven Bethard
    Replies:
    2
    Views:
    458
    Steven Bethard
    Feb 16, 2005
  4. Kent Johnson
    Replies:
    7
    Views:
    915
    Jan Niklas Fingerle
    Feb 12, 2006
  5. Ramchandra Apte
    Replies:
    17
    Views:
    342
    Manuel Pégourié-Gonnard
    Sep 30, 2012
Loading...

Share This Page