super() doesn't get superclass

Discussion in 'Python' started by Ben Finney, Sep 18, 2007.

  1. Ben Finney

    Ben Finney Guest

    Howdy all,

    After banging my head against super() trying to reliably get
    attributes of a superclass, I gained a little enlightenment when this
    turned up in a search:

    "Python's Super is nifty, but you can't use it
    (Previously: Python's Super Considered Harmful)"
    <URL:http://fuhm.org/super-harmful/>

    An early paragraph stood out that made my current problems clear:

    One big problem with 'super' is that it sounds like it will cause
    the superclass's copy of the method to be called. This is simply
    not the case, it causes the next method in the MRO to be called.

    Oh. The author's right, I got that mistaken impression too. Obviously,
    then, I must have misread the documentation of 'super'. I went back to
    double-check, and was appalled to find:

    super(type[, object-or-type])
    Return the superclass of type. [...]

    <URL:http://docs.python.org/lib/built-in-funcs.html#l2h-72>

    Why does the documentation of 'super' say that it returns the
    superclass when *that's not true*? It doesn't return the superclass,
    it returns the next class in the MRO, whether that's a superclass or
    not.

    Actually, even that's not true. The error message "AttributeError:
    'super' object has no attribute 'bazfunc'" makes it clear that 'super'
    actually returns not the superclass, but a 'super' object, whatever
    that's supposed to be.


    After reading the rest of the article, I'm amazed that 'super' as
    currently implemented is in Python at all. I agree with the author
    that it's useless unless *everyone* uses it for *everything*, and even
    then it's pretty limited.

    One thing's for sure, it's badly misnamed, and falsely documented.

    Can anyone point me to a counter-argument to the above article?

    --
    \ "The World is not dangerous because of those who do harm but |
    `\ because of those who look at it without doing anything." |
    _o__) —Albert Einstein |
    Ben Finney
     
    Ben Finney, Sep 18, 2007
    #1
    1. Advertising

  2. Ben Finney

    Evan Klitzke Guest

    On Tue, 2007-09-18 at 14:15 +1000, Ben Finney wrote:
    > Howdy all,
    >
    > After banging my head against super() trying to reliably get
    > attributes of a superclass, I gained a little enlightenment when this
    > turned up in a search:
    >
    > "Python's Super is nifty, but you can't use it
    > (Previously: Python's Super Considered Harmful)"
    > <URL:http://fuhm.org/super-harmful/>
    >
    > An early paragraph stood out that made my current problems clear:
    >
    > One big problem with 'super' is that it sounds like it will cause
    > the superclass's copy of the method to be called. This is simply
    > not the case, it causes the next method in the MRO to be called.
    >
    > Oh. The author's right, I got that mistaken impression too. Obviously,
    > then, I must have misread the documentation of 'super'. I went back to
    > double-check, and was appalled to find:
    >
    > super(type[, object-or-type])
    > Return the superclass of type. [...]
    >
    > <URL:http://docs.python.org/lib/built-in-funcs.html#l2h-72>
    >
    > Why does the documentation of 'super' say that it returns the
    > superclass when *that's not true*? It doesn't return the superclass,
    > it returns the next class in the MRO, whether that's a superclass or
    > not.


    The next class in the MRO _is_ a superclass. Maybe not the way you've
    defined it in your own code, but certainly of the new class you created
    with MI.

    > Actually, even that's not true. The error message "AttributeError:
    > 'super' object has no attribute 'bazfunc'" makes it clear that 'super'
    > actually returns not the superclass, but a 'super' object, whatever
    > that's supposed to be.


    No, super really does return a class. What makes you think that super
    returns a special sort of object?

    > After reading the rest of the article, I'm amazed that 'super' as
    > currently implemented is in Python at all. I agree with the author
    > that it's useless unless *everyone* uses it for *everything*, and even
    > then it's pretty limited.


    I don't see what the problem is. If you don't use super, then you can
    break the inheritance chain, but this is no different than calling
    superclass methods by passing in self (i.e. the old-style way of doing
    it), and in fact using super is far more flexible. There's no way to
    magically know when to call the superclass' method, and even if you knew
    when, there's no way to magically know when it needs to be called.

    If you're using multiple inheritance, and you're _not_ using super
    everywhere, then your code is broken anyway. Use super correctly in your
    own code, and you don't need to worry about other people using it
    incorrectly.

    --
    Evan Klitzke <>
     
    Evan Klitzke, Sep 18, 2007
    #2
    1. Advertising

  3. Ben Finney

    Ben Finney Guest

    Evan Klitzke <> writes:

    > On Tue, 2007-09-18 at 14:15 +1000, Ben Finney wrote:
    > > Why does the documentation of 'super' say that it returns the
    > > superclass when *that's not true*? It doesn't return the
    > > superclass, it returns the next class in the MRO, whether that's a
    > > superclass or not.

    >
    > The next class in the MRO _is_ a superclass. Maybe not the way
    > you've defined it in your own code, but certainly of the new class
    > you created with MI.


    If I define a class hierarchy as follows::

    class A(object): pass
    class B(object): pass
    class C(A): pass
    class D(B): pass

    is it true to say that "D is a superclass of A"? No, because they're
    entirely unrelated except that they inherit from 'object'. The
    superclass of 'A' is 'object'.

    How about this:

    class E(C, D): pass

    In this instance, the MRO now has D following A; but the superclass of
    'A' is still 'object'.

    You seem to be saying that now suddenly D *is* a superclass of
    A. That's certainly not what users will think of when they think
    "superclass" though.

    > > Actually, even that's not true. The error message "AttributeError:
    > > 'super' object has no attribute 'bazfunc'" makes it clear that
    > > 'super' actually returns not the superclass, but a 'super' object,
    > > whatever that's supposed to be.

    >
    > No, super really does return a class. What makes you think that
    > super returns a special sort of object?


    >>> super(A)

    <super: <class 'A'>, NULL>
    >>> super(A).__class__

    <type 'super'>

    What I expect, incidentally, is that a function documented as "returns
    the superclass of 'type'" would actually return that class (in this
    case, the type 'object'), not an object of 'super' type.

    > > After reading the rest of the article, I'm amazed that 'super' as
    > > currently implemented is in Python at all. I agree with the author
    > > that it's useless unless *everyone* uses it for *everything*, and
    > > even then it's pretty limited.

    >
    > I don't see what the problem is. If you don't use super, then you can
    > break the inheritance chain


    I don't want to break the inheritance chain. I want the superclass,
    not the "next class in the MRO".

    Orthogonally to that, I think it's madness to write a function for
    "return the next class in the MRO for 'type'" and document it as
    "return the superclass of 'type'".

    Am I mistaken in thinking that "superclass of foo" is equivalent to
    "parent class of foo"? If so, I'd lay heavy odds that I'm not alone in
    that thinking.

    --
    \ "Laugh and the world laughs with you; snore and you sleep |
    `\ alone." —anonymous |
    _o__) |
    Ben Finney
     
    Ben Finney, Sep 18, 2007
    #3
  4. Ben Finney <> wrote:

    > Am I mistaken in thinking that "superclass of foo" is equivalent to
    > "parent class of foo"? If so, I'd lay heavy odds that I'm not alone in
    > that thinking.


    "That thinking" (confusing "parent" with "ancestor") makes sense only
    (if at all) in a single-inheritance world. Python's super() exists to
    support MULTIPLE inheritance.

    In general, "a superclass of foo" means "a class X such that foo is a
    sublass of X" and thus applies to all parents, all parents of parents,
    and so on ("issubclass" does NOT mean "is a DIRECT AND IMMEDIATE
    subclass", but "is a subclass"; check the Python builtin function of
    that name).


    Alex
     
    Alex Martelli, Sep 18, 2007
    #4
  5. Ben Finney

    Ben Finney Guest

    Evan Klitzke <> writes:

    > If you're using multiple inheritance, and you're _not_ using super
    > everywhere, then your code is broken anyway.


    This seems to support the notion that 'super' is unusable. If I
    inherit from code that isn't under my control, and then use super(),
    my code is broken.

    Therefore, to avoid writing broken code, I must either never inherit
    from code not under my control, or I must never use super(). Since the
    former is practically unavoidable, I must choose the latter.

    Which, naturally, compounds the problem, since when someone else uses
    *my* code, they in turn must conclude that they can't use super().

    > Use super correctly in your own code, and you don't need to worry
    > about other people using it incorrectly.


    As the article points out, when using super(),

    you must remember that super does not call your superclass. You
    must be prepared to call any other class's method in the hierarchy
    and be prepared to be called from any other class's method.

    So, the programmer using super() very much *does* need to worry about
    other people using it correctly.

    --
    \ "Quidquid latine dictum sit, altum viditur." ("Whatever is |
    `\ said in Latin, sounds profound.") -- Anonymous |
    _o__) |
    Ben Finney
     
    Ben Finney, Sep 18, 2007
    #5
  6. Ben Finney

    Ben Finney Guest

    (Alex Martelli) writes:

    > In general, "a superclass of foo" means "a class X such that foo is a
    > sublass of X"


    Sure. However, this doesn't equate to the assertion that "next class
    in the MRO is the superclass", which is what I was responding to.

    --
    \ "Even if the voices in my head are not real, they have pretty |
    `\ good ideas." —anonymous |
    _o__) |
    Ben Finney
     
    Ben Finney, Sep 18, 2007
    #6
  7. Ben Finney

    Ben Finney Guest

    Sorry, I read your message too fast and responded to the wrong point
    :)

    (Alex Martelli) writes:

    > Ben Finney <> wrote:
    > > Am I mistaken in thinking that "superclass of foo" is equivalent
    > > to "parent class of foo"? If so, I'd lay heavy odds that I'm not
    > > alone in that thinking.

    >
    > In general, "a superclass of foo" means "a class X such that foo is a
    > sublass of X"


    Read "ancestor" where I wrote "parent", then. It seems that (with that
    substitution) my thinking is correct. Yes?

    Why, then, does super() traverse the MRO of class 'A', instead of the
    ancestors of class 'A'? And, since that's what it does, is it not
    misnamed, since "next in the MRO" is *not* the same thing as
    "superclass"?

    --
    \ "Remember: every member of your 'target audience' also owns a |
    `\ broadcasting station. These 'targets' can shoot back." -- |
    _o__) Michael Rathbun to advertisers, news.admin.net-abuse.email |
    Ben Finney
     
    Ben Finney, Sep 18, 2007
    #7
  8. Ben Finney

    Carl Banks Guest

    On Tue, 18 Sep 2007 15:38:46 +1000, Ben Finney wrote:
    > Evan Klitzke <> writes:
    >
    >> If you're using multiple inheritance, and you're _not_ using super
    >> everywhere, then your code is broken anyway.

    >
    > This seems to support the notion that 'super' is unusable. If I inherit
    > from code that isn't under my control, and then use super(), my code is
    > broken.
    >
    > Therefore, to avoid writing broken code, I must either never inherit
    > from code not under my control, or I must never use super(). Since the
    > former is practically unavoidable, I must choose the latter.
    >
    > Which, naturally, compounds the problem, since when someone else uses
    > *my* code, they in turn must conclude that they can't use super().


    I'm sorry, but you can't inherit from someone else's classes and not
    worry about what they're doing. Whether they use super or not is only
    one possible concern. It's not like the super destroyed the magical
    utopia where you could derive from other people's classes without worry.

    In any case, it's just as problematic if you don't use super and your
    base classes do. By your logic, your code is "broken" no matter what you
    do, and so the only "conclusion" you can come to is never to derive from
    classes that aren't under your control.

    (Which, frankly, isn't all that bad a conclusion. In 8 years of Python
    programming, I've inherited from exactly one class that wasn't under my
    control: Thread. It's not "practically impossible" to avoid, at least
    not for me.)


    >> Use super correctly in your own code, and you don't need to worry about
    >> other people using it incorrectly.

    >
    > As the article points out, when using super(),
    >
    > you must remember that super does not call your superclass. You must
    > be prepared to call any other class's method in the hierarchy and be
    > prepared to be called from any other class's method.
    >
    > So, the programmer using super() very much *does* need to worry about
    > other people using it correctly.


    Yes. Welcome to programming.


    Carl Banks
     
    Carl Banks, Sep 18, 2007
    #8
  9. Ben Finney a écrit :
    > Evan Klitzke <> writes:
    >
    >> On Tue, 2007-09-18 at 14:15 +1000, Ben Finney wrote:
    >>> Why does the documentation of 'super' say that it returns the
    >>> superclass when *that's not true*? It doesn't return the
    >>> superclass, it returns the next class in the MRO, whether that's a
    >>> superclass or not.

    >> The next class in the MRO _is_ a superclass. Maybe not the way
    >> you've defined it in your own code, but certainly of the new class
    >> you created with MI.

    >
    > If I define a class hierarchy as follows::
    >
    > class A(object): pass
    > class B(object): pass
    > class C(A): pass
    > class D(B): pass
    >
    > is it true to say that "D is a superclass of A"?


    Obviously not.

    > How about this:
    >
    > class E(C, D): pass
    >
    > In this instance, the MRO now has D following A; but the superclass of
    > 'A' is still 'object'.


    Yes. And ?

    >
    > You seem to be saying that now suddenly D *is* a superclass of
    > A.


    I don't see such an assertion in Evan's answer. Chapter and verse ???

    > That's certainly not what users will think of when they think
    > "superclass" though.


    If a class X is in the MRO of call Y, then X is a superclass of Y. I
    agree that the documentation for super is somewhat misleading (and
    obviously wrong), but it still *give access to* (at least one of) the
    superclass(es).

    >>> Actually, even that's not true. The error message "AttributeError:
    >>> 'super' object has no attribute 'bazfunc'" makes it clear that
    >>> 'super' actually returns not the superclass, but a 'super' object,
    >>> whatever that's supposed to be.


    The 'super' object is a wrapper around a class and an object. It
    delegates attribute lookups to appropriate superclass.

    >>> After reading the rest of the article, I'm amazed that 'super' as
    >>> currently implemented is in Python at all.


    If you have a better solution for handling multiple inheritence, please
    share with us.

    FWIW, after all the articles I've read explaining why Python is badly
    designed, badly implemented, and totally flawed, I do wonder why this
    language exists at all !-)

    > I don't want to break the inheritance chain. I want the superclass,


    A soon as you have either multiple inheritence and/or an inheritence
    tree with depth > 1, there's no such thing as "the" superclass. wrt/
    your exemple, object, A, B, C and D are *all* superclasses of E.

    > not the "next class in the MRO".


    The next class in the MRO is (usually and AFAICT) the most direct
    superclass.

    > Orthogonally to that, I think it's madness to write a function for
    > "return the next class in the MRO for 'type'" and document it as
    > "return the superclass of 'type'".


    I wouldn't use such an extreme word as 'madness', but I totally agree
    that this should be corrected. Care to submit a doc patch ?
     
    Bruno Desthuilliers, Sep 18, 2007
    #9
  10. Bruno Desthuilliers <> writes:

    > If a class X is in the MRO of call Y, then X is a superclass of Y. I
    > agree that the documentation for super is somewhat misleading (and
    > obviously wrong), but it still *give access to* (at least one of)
    > the superclass(es).


    I believe the confusion comes from different assumptions about what
    "superclasses" refers to. super() iterates over superclasses of the
    *instance* in use, but an individual call to super does not
    necessarily invoke the superclass of the *implementation* of the
    method. For example, given a random class:

    class X(Y):
    def foo(self):
    super(X, self).foo()

    ....there is in fact no guarantee that super() calls a superclass of
    X. However, it is certainly guaranteed that it will call a superclass
    of type(self).

    Pre-2.2 Python used a simpler scheme where the superclass was always
    called, but it caused problems with diamond inheritance where some
    methods would be called either twice or not at all. (This is
    explained in http://www.python.org/download/releases/2.2.3/descrintro/
    in some detail.)
     
    Hrvoje Niksic, Sep 18, 2007
    #10
  11. Ben Finney

    Ben Finney Guest

    Bruno Desthuilliers <> writes:

    > Ben Finney a écrit :
    > > Evan Klitzke <> writes:
    > >> On Tue, 2007-09-18 at 14:15 +1000, Ben Finney wrote:
    > >>> [the 'super' function] doesn't return the superclass, it returns
    > >>> the next class in the MRO, whether that's a superclass or not.
    > >> The next class in the MRO _is_ a superclass.

    > >
    > > [demonstration that the next class in the MRO is not necessarily a
    > > superclass]
    > >
    > > You seem to be saying that now suddenly D *is* a superclass of
    > > A.

    >
    > I don't see such an assertion in Evan's answer. Chapter and verse
    > ???


    I've trimmed the quoting to make it clearer.

    Evan is claiming that "the next class in the MRO _is_ a superclass",
    apparently by his definition or some other that I've not seen.

    I've shown a fairly simple multiple-inheritance hierarchy where the
    next class in the MRO is not an ancestor of the subject class, but is
    instead a class that merely shares a common ancestor.

    Either "superclass of A" is equivalent to "ancestor class of A", or
    it's not. I maintain that many programmers will expect that it is, but
    Evan's assertion says otherwise. It can't be both.

    > > That's certainly not what users will think of when they think
    > > "superclass" though.

    >
    > If a class X is in the MRO of call Y, then X is a superclass of Y.


    That goes completely against what Alex Martelli told me, which was
    that "superclass" can be thought of as synonymous with "ancestor".

    > I agree that the documentation for super is somewhat misleading (and
    > obviously wrong),


    Well, that's the first time someone has acknowledged that in this
    thread, so I guess this is something.

    > but it still *give access to* (at least one of) the superclass(es).


    Only if you allow "some class somewhere in the inheritance tree, even
    one this class never inherited from directly or indirectly" to be in
    the definition of "superclass".

    I'm arguing that what people mean by "superclass" is "a direct or
    indirect ancestor class", and it's highly misleading to imply that by
    the function name what that's not what the function does.

    > >>> After reading the rest of the article, I'm amazed that 'super'
    > >>> as currently implemented is in Python at all.

    >
    > If you have a better solution for handling multiple inheritence,
    > please share with us.


    My concern is to at least not *directly mislead* the programmer
    through a badly-named function. If 'super' can invoke a non-superclass
    — if instead it gets "the next class in the MRO" — then this is at the
    least badly-named.

    > FWIW, after all the articles I've read explaining why Python is
    > badly designed, badly implemented, and totally flawed, I do wonder
    > why this language exists at all !-)


    In most of those arguments I'm firmly on the side of the Python
    designers. Not on this one.

    > > I don't want to break the inheritance chain. I want the
    > > superclass,

    >
    > A soon as you have either multiple inheritence and/or an inheritence
    > tree with depth > 1, there's no such thing as "the" superclass. wrt/
    > your exemple, object, A, B, C and D are *all* superclasses of E.


    Yes, they are. But my example was not "get the superclass of E", but
    "get the superclass of A".

    The *only* ancestor of 'A' in the example is 'object', so I expect
    "superclass of A" to *always* get 'object'. But that's not what
    happens!

    Instead, it *sometimes* gets 'object', and *sometimes* gets 'D' —
    depending on who has inherited from a class that isn't even 'A'!
    That's what makes 'super' definitely misnamed, and practically
    unusable.

    > The next class in the MRO is (usually and AFAICT) the most direct
    > superclass.


    Demonstrably not, in the examples given in
    <URL:http://fuhm.org/super-harmful/>.

    > I wouldn't use such an extreme word as 'madness', but I totally agree
    > that this should be corrected. Care to submit a doc patch ?


    I don't understand what practical uses 'super' is intended for (only
    that they don't seem to match any of my needs), so the only
    replacement I would come up with would not be constructive.

    --
    \ "A computer once beat me at chess, but it was no match for me |
    `\ at kick boxing." -- Emo Philips |
    _o__) |
    Ben Finney
     
    Ben Finney, Sep 19, 2007
    #11
  12. Ben Finney

    Ben Finney Guest

    Hrvoje Niksic <> writes:

    > class X(Y):
    > def foo(self):
    > super(X, self).foo()
    >
    > ...there is in fact no guarantee that super() calls a superclass of
    > X. However, it is certainly guaranteed that it will call a superclass
    > of type(self).


    Not even that. It could call *any class in the inheritance hierarchy*,
    depending on how the MRO has resolved "next class". Even one that is
    neither an ancestor nor a descendant of X.

    --
    \ "When I was a kid I used to pray every night for a new bicycle. |
    `\ Then I realised that the Lord doesn't work that way so I stole |
    _o__) one and asked Him to forgive me." -- Emo Philips |
    Ben Finney
     
    Ben Finney, Sep 19, 2007
    #12
  13. On Wed, 19 Sep 2007 09:11:37 +1000, Ben Finney
    <> declaimed the following in
    comp.lang.python:

    >
    > Instead, it *sometimes* gets 'object', and *sometimes* gets 'D' —
    > depending on who has inherited from a class that isn't even 'A'!
    > That's what makes 'super' definitely misnamed, and practically
    > unusable.
    >

    Try to interpret it as:

    Get the next superclass that is in the MRO /after/ the position of
    "my class" in that MRO (which is that of the /starting/ instance; the
    "self" that keeps getting passed down through the calls)

    At least, when multiple inheritance examples have been shown before,
    that is the way I've seen the system resolve...
    --
    Wulfraed Dennis Lee Bieber KD6MOG

    HTTP://wlfraed.home.netcom.com/
    (Bestiaria Support Staff: )
    HTTP://www.bestiaria.com/
     
    Dennis Lee Bieber, Sep 19, 2007
    #13
  14. On Sep 18, 12:15 am, Ben Finney <> wrote:
    > Howdy all,
    >
    > After banging my head against super() trying to reliably get
    > attributes of a superclass, I gained a little enlightenment when this
    > turned up in a search:
    >
    > "Python's Super is nifty, but you can't use it
    > (Previously: Python's Super Considered Harmful)"
    > <URL:http://fuhm.org/super-harmful/>
    >
    > An early paragraph stood out that made my current problems clear:
    >
    > One big problem with 'super' is that it sounds like it will cause
    > the superclass's copy of the method to be called. This is simply
    > not the case, it causes the next method in the MRO to be called.
    >
    > Oh. The author's right, I got that mistaken impression too. Obviously,
    > then, I must have misread the documentation of 'super'. I went back to
    > double-check, and was appalled to find:
    >
    > super(type[, object-or-type])
    > Return the superclass of type. [...]
    >
    > <URL:http://docs.python.org/lib/built-in-funcs.html#l2h-72>
    >
    > Why does the documentation of 'super' say that it returns the
    > superclass when *that's not true*? It doesn't return the superclass,
    > it returns the next class in the MRO, whether that's a superclass or
    > not.
    >
    > Actually, even that's not true. The error message "AttributeError:
    > 'super' object has no attribute 'bazfunc'" makes it clear that 'super'
    > actually returns not the superclass, but a 'super' object, whatever
    > that's supposed to be.
    >
    > After reading the rest of the article, I'm amazed that 'super' as
    > currently implemented is in Python at all. I agree with the author
    > that it's useless unless *everyone* uses it for *everything*, and even
    > then it's pretty limited.
    >
    > One thing's for sure, it's badly misnamed, and falsely documented.


    You are right, I think I even filed a documentation bug for
    that years ago, and I wrote an entire paper on the subject that
    however I never published since I never felt 100% confident
    with super (and I had other fishes to fry ;)
    I realize now that I was wrong in not publishing it.
    You can find the draft (warning: it is a draft, I did
    not check the examples there, they are likely broken)
    here:

    http://www.phyast.pitt.edu/~micheles/python/super.html

    It begins as follows:

    """
    The truth about super
    Author: Michele Simionato
    Date: June 2004
    Status: Draft

    super is a new built-in, first introduced in Python 2.2 and slightly
    improved and fixed in Python 2.3, which is little known to the average
    Python programmer. One of the reason for this fact is its poor
    documentation`: at the time of this writing (June 2004) super
    documentation is incomplete and in some parts misleading and even
    wrong. For instance, it was recently pointed out on comp.lang.python
    that the standard library (Python 2.3.4, section 2.1) still says:

    super(type[, object-or-type])
    Return the superclass of type. If the second argument is omitted
    the
    super object returned is unbound. If the second argument is an
    object,
    isinstance(obj, type) must be true. If the second argument is a
    type,
    issubclass(type2, type) must be true. super() only works for new-
    style
    classes.

    The first sentence is just plain wrong. super does not return the
    superclass. There is no such a thing as "the" superclass in a Multiple
    Inheritance (MI) language. Also, the sentence about 'unbound' is
    misleading, since it may easily lead the programmer to think about
    bound and unbound methods, whereas it has nothing to do with that
    concept. Finally, there subtle pitfalls of super which are not at all
    mentioned. IMNSHO super is one of the most trickiest and surprising
    Python constructs, so it absolutely needs a document to share light on
    some of his secrets: the present article aims to fix the issues with
    the current documentation, and tell you the "truth" about super. At
    least the amount of truth I have discovered with my experimentations,
    which is certainly not the whole truth ;)

    Here is the plan: first I will discuss the concept of superclass in a
    Multiple Inheritance (MI) world (there is no such a thing as "the"
    superclass!); second, I will show that super is a proxy object, able
    to dispatch to the right methods/attributes in the MRO; third,

    recall some background on how the resolution of methods works on how
    descriptors work and (essentially pointing out to the standard
    references); then I will discuss the more common invocation of super -
    the invocation with two arguments - and finally I will discuss the
    most tricky part, i.e. invoking super with just one argument and I
    will discuss pitfalls.

    Finally, a fair warning: this document is aimed to expert Pythonistas.
    It is not for the faint of heart ;)
    """
     
    Michele Simionato, Sep 19, 2007
    #14
  15. Ben Finney

    Ben Finney Guest

    Dennis Lee Bieber <> writes:

    > Try to interpret it as:


    My point exactly. If a function is named 'super' and operates on
    classes, it's a pretty strong implication that it's about
    superclasses. Any explanation that begins "Try to interpret it as" and
    then goes on to explain that it's to do with MRO, *not* superclasses,
    is evidence that the function is *badly named*.

    I'm not interested in documenting this function, because as I said I
    don't see why I would want to use it. My objection is that, as
    currently named, it's an *obstacle* when a programmer goes looking for
    a way to get a superclass.

    Possibly the name 'next_in_mro', while ugly, would at least match the
    actual behaviour of this function.

    At least then the next person who goes looking for "how do I get the
    superclass of A?" won't be misled into trying to use *the wrong
    function for that purpose*.

    --
    \ "If you can't annoy somebody there is little point in writing." |
    `\ -- Kingsley Amis |
    _o__) |
    Ben Finney
     
    Ben Finney, Sep 19, 2007
    #15
  16. Ben Finney

    Paul Rudin Guest

    Ben Finney <> writes:


    > Possibly the name 'next_in_mro', while ugly, would at least match the
    > actual behaviour of this function.


    In common lisp there's (call-next-method ...)
     
    Paul Rudin, Sep 19, 2007
    #16
  17. Ben Finney <> writes:

    > Hrvoje Niksic <> writes:
    >
    >> class X(Y):
    >> def foo(self):
    >> super(X, self).foo()
    >>
    >> ...there is in fact no guarantee that super() calls a superclass of
    >> X. However, it is certainly guaranteed that it will call a superclass
    >> of type(self).

    >
    > Not even that. It could call *any class in the inheritance
    > hierarchy*,


    The inheritance hierarchiy is populated by the various (direct and
    indirect) superclasses of type(self).

    > depending on how the MRO has resolved "next class". Even one that is
    > neither an ancestor nor a descendant of X.


    My point exactly. superclass of X is not the same as superclass of
    type(self). Super iterates over the latter, where you expect the
    former.
     
    Hrvoje Niksic, Sep 19, 2007
    #17
  18. Ben Finney <> writes:

    > Evan is claiming that "the next class in the MRO _is_ a superclass",
    > apparently by his definition or some other that I've not seen.


    The definition of superclass is not the issue, the issue is
    "superclass *of which class*"? You expect super(A, self) to iterate
    only over superclasses of A, even when self is an instance of a
    subtype of A. What really happens is that super(A, self) yields the
    next method in type(self)'s MRO, which can and does cause include
    classes that are not by any definition superclasses of A. All of
    those classes are, however, superclasses of the instance's type.

    I think it is not possible to have super(A, self) only call
    superclasses of A and at the same time having multiple inheritance
    work without calling some methods in the hierarchy twice or not at
    all. Guido's paper at http://tinyurl.com/qkjgp explains the reasoning
    behind super in some detail.

    >> I agree that the documentation for super is somewhat misleading (and
    >> obviously wrong),

    >
    > Well, that's the first time someone has acknowledged that in this
    > thread, so I guess this is something.


    For the record, I also agree with that. The documentation should
    document in some detail that super(type, obj) yields superclasses of
    type(obj), not of type, and that the "type" argument is only used for
    super to be able to locate the next type in the list.

    >> I wouldn't use such an extreme word as 'madness', but I totally agree
    >> that this should be corrected. Care to submit a doc patch ?

    >
    > I don't understand what practical uses 'super' is intended for


    It's intended for cooperative multiple inheritance, a la CLOS's
    call-next-method.
     
    Hrvoje Niksic, Sep 19, 2007
    #18
  19. Ben Finney a écrit :
    > Bruno Desthuilliers <> writes:
    >
    >> Ben Finney a écrit :
    >>> Evan Klitzke <> writes:
    >>>> On Tue, 2007-09-18 at 14:15 +1000, Ben Finney wrote:
    >>>>> [the 'super' function] doesn't return the superclass, it returns
    >>>>> the next class in the MRO, whether that's a superclass or not.
    >>>> The next class in the MRO _is_ a superclass.
    >>> [demonstration that the next class in the MRO is not necessarily a
    >>> superclass]
    >>>
    >>> You seem to be saying that now suddenly D *is* a superclass of
    >>> A.

    >> I don't see such an assertion in Evan's answer. Chapter and verse
    >> ???

    >
    > I've trimmed the quoting to make it clearer.
    >
    > Evan is claiming that "the next class in the MRO _is_ a superclass",
    > apparently by his definition or some other that I've not seen.


    The next class in the MRO *is* a superclass of the *instance*. Else it
    wouldn't be in the MRO !-)

    > I've shown a fairly simple multiple-inheritance hierarchy where the
    > next class in the MRO is not an ancestor of the subject class,


    It's an ancestor of the class of the instance on which the method is
    called.

    > Either "superclass of A" is equivalent to "ancestor class of A", or
    > it's not. I maintain that many programmers will expect that it is, but
    > Evan's assertion says otherwise. It can't be both.
    >
    >>> That's certainly not what users will think of when they think
    >>> "superclass" though.

    >> If a class X is in the MRO of call Y, then X is a superclass of Y.


    s/call/class/, of course.


    > That goes completely against what Alex Martelli told me, which was
    > that "superclass" can be thought of as synonymous with "ancestor".


    Pardon ???

    I repeat: if class X is in the MRO of class Y, then X is a superclass of
    class Y. Which indeed makes X an ancestor of Y.

    >> I agree that the documentation for super is somewhat misleading (and
    >> obviously wrong),

    >
    > Well, that's the first time someone has acknowledged that in this
    > thread, so I guess this is something.


    OTHO, I don't think anyone here stated that the doc was right !-)

    >> but it still *give access to* (at least one of) the superclass(es).

    >
    > Only if you allow "some class somewhere in the inheritance tree, even
    > one this class never inherited from directly or indirectly" to be in
    > the definition of "superclass".


    By definition, if the class is in the inheritence tree, then this class
    is inherited from directly or indirectly. FWIW, I've never caught
    super() calling a class that was not in the inheritence tree of the
    instance passed to it... If you noticed such a thing, then by all mean
    fill a bug report.

    > I'm arguing that what people mean by "superclass" is "a direct or
    > indirect ancestor class", and it's highly misleading to imply that by
    > the function name what that's not what the function does.


    Please remember that super() is usually called with *2* arguments : the
    class in which the method is defined (let's call this class C), *and* an
    instance. This instance may be an instance of a *subclass* of C. So the
    MRO to consider is the MRO *of the instance*. Else, super would be
    totally useless.

    >>>>> After reading the rest of the article, I'm amazed that 'super'
    >>>>> as currently implemented is in Python at all.

    >> If you have a better solution for handling multiple inheritence,
    >> please share with us.

    >
    > My concern is to at least not *directly mislead* the programmer
    > through a badly-named


    Or badly documented

    > function


    class. super is not a function, it's a class.

    > If 'super' can invoke a non-superclass


    super won't never "invoke" anything that's not in the MRO of the
    *instance* passed to it.

    > — if instead it gets "the next class in the MRO" — then this is at the
    > least badly-named.


    Possibly, but this is another point.

    >> FWIW, after all the articles I've read explaining why Python is
    >> badly designed, badly implemented, and totally flawed, I do wonder
    >> why this language exists at all !-)

    >
    > In most of those arguments I'm firmly on the side of the Python
    > designers. Not on this one.


    Well, I understand that you disagree with both the documention and the
    name of super. As far as I'm concerned, the mere fact that this
    discussion happens is probably a sign that there's something to be fixed
    here - at least wrt documentation, possibly wrt/ naming. But the
    *feature* by itself is certainly something we do want to keep, whatever
    some may argue.

    >>> I don't want to break the inheritance chain. I want the
    >>> superclass,

    >> A soon as you have either multiple inheritence and/or an inheritence
    >> tree with depth > 1, there's no such thing as "the" superclass. wrt/
    >> your exemple, object, A, B, C and D are *all* superclasses of E.

    >
    > Yes, they are. But my example was not "get the superclass of E", but
    > "get the superclass of A".


    You wrote:

    """
    If I define a class hierarchy as follows::

    class A(object): pass
    class B(object): pass
    class C(A): pass
    class D(B): pass

    is it true to say that "D is a superclass of A"? No, because they're
    entirely unrelated except that they inherit from 'object'. The
    superclass of 'A' is 'object'.

    How about this:

    class E(C, D): pass

    In this instance, the MRO now has D following A; but the superclass of
    'A' is still 'object'.
    """

    If I understand correctly, your concerns are with the superclass*es* of
    E, not with the superclass of A.

    > The *only* ancestor of 'A' in the example is 'object',


    Yes.

    > so I expect
    > "superclass of A" to *always* get 'object'. But that's not what
    > happens!


    superclass of A is object, no problem. But the next (according to the
    MRO you defined) superclass of an instance of E is not necessarily A...

    > Instead, it *sometimes* gets 'object', and *sometimes* gets 'D' —
    > depending on who has inherited from a class that isn't even 'A'!
    > That's what makes 'super' definitely misnamed,


    Badly documented, and (very) possibly (as this whole thread illustrates)
    misnamed...

    > and practically
    > unusable.


    And perfectly usable. At least once you understand what it's for.

    >> The next class in the MRO is (usually and AFAICT) the most direct
    >> superclass.

    >
    > Demonstrably not, in the examples given in
    > <URL:http://fuhm.org/super-harmful/>.
    >
    >> I wouldn't use such an extreme word as 'madness', but I totally agree
    >> that this should be corrected. Care to submit a doc patch ?

    >
    > I don't understand what practical uses 'super' is intended for


    There's a whole article on it on python.org:
    http://www.python.org/download/releases/2.2/descrintro/#cooperation

    The goal is to call the correct "next" method according to MRO. Indeed,
    it could have been name "call_next_method".

    > (only
    > that they don't seem to match any of my needs),


    If all you want is to get at the direct ancestor of the *class* in wich
    a method is defined, the solution is well-known and quite obvious: call
    this class directly. ie:

    class A(object):
    def __init__(self):
    print "A.__init__"

    class B(object):
    def __init__(self):
    A.__init__(self)
    print "B.__init__"


    Note that in this case, you'll get exactly the same result with :

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


    super is only useful when MI comes in play - which BTW is not that
    common in Python.
     
    Bruno Desthuilliers, Sep 19, 2007
    #19
  20. On Sep 19, 12:36 pm, Bruno Desthuilliers <bruno.
    > wrote:

    > The next class in the MRO *is* a superclass of the *instance*. Else it
    > wouldn't be in the MRO !-)


    Bruno, there is no such a thing as a superclass in a multiple
    inheritance
    world, and it is a very bad idea to continue to use that terminology.
    I was
    convinced of that by Bjorn Pettersen in a thread on comp.lang.python
    in May 2003
    and you may Google for it. You may find there convincing arguments
    against the
    superclass concept, some of which I report in
    http://www.phyast.pitt.edu/~micheles/python/super.html

    > Well, I understand that you disagree with both the documention and the
    > name of super. As far as I'm concerned, the mere fact that this
    > discussion happens is probably a sign that there's something to be fixed
    > here - at least wrt documentation, possibly wrt/ naming. But the
    > *feature* by itself is certainly something we do want to keep, whatever
    > some may argue.


    Well, I am personally *against* multiple inheritance (i.e. IMO it
    gives more
    troubles than advantages)
    >
    > The goal is to call the correct "next" method according to MRO. Indeed,
    > it could have been name "call_next_method".


    Right.

    Michele Simionato
     
    Michele Simionato, Sep 19, 2007
    #20
    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,844
    Darryl Pierce
    Feb 24, 2005
  2. chriss
    Replies:
    3
    Views:
    478
    chriss
    Sep 10, 2005
  3. Evan Klitzke
    Replies:
    0
    Views:
    385
    Evan Klitzke
    Aug 2, 2007
  4. bart van deenen
    Replies:
    6
    Views:
    804
    bart van deenen
    Mar 3, 2009
  5. Fred
    Replies:
    4
    Views:
    528
    Roedy Green
    Dec 28, 2010
Loading...

Share This Page