trouble understanding super()

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • John Salerno

    #1

    trouble understanding super()

    Here's some code from Python in a Nutshell. The comments are lines from
    a previous example that the calls to super replace in the new example:

    class A(object):
    def met(self):
    print 'A.met'

    class B(A):
    def met(self):
    print 'B.met'
    # A.met(self)
    super(B, self).met()

    class C(A):
    def met(self):
    print 'C.met'
    # A.met(self)
    super(C, self).met()

    class D(B, C):
    def met(self):
    print 'D.met'
    # B.met()
    # C.met()
    super(D, self).met()

    Then you call D().met()

    Now, I understand that the commented code would cause A.met to be called
    twice. But why does the second version (with super) not also do this? I
    guess my problem lies in not understanding exactly what the super
    function returns.

    super(D, self).met() seems like it would return something that has to do
    with both B and C, which each in turn return a superobject having to do
    with A, so why isn't A.met called twice still?

    Thanks!
  • Simon Forman

    #2
    Re: trouble understanding super()

    John Salerno wrote:
    Here's some code from Python in a Nutshell. The comments are lines from
    a previous example that the calls to super replace in the new example:
    >
    class A(object):
    def met(self):
    print 'A.met'
    >
    class B(A):
    def met(self):
    print 'B.met'
    # A.met(self)
    super(B, self).met()
    >
    class C(A):
    def met(self):
    print 'C.met'
    # A.met(self)
    super(C, self).met()
    >
    class D(B, C):
    def met(self):
    print 'D.met'
    # B.met()
    # C.met()
    super(D, self).met()
    >
    Then you call D().met()
    >
    Now, I understand that the commented code would cause A.met to be called
    twice. But why does the second version (with super) not also do this? I
    guess my problem lies in not understanding exactly what the super
    function returns.
    >
    super(D, self).met() seems like it would return something that has to do
    with both B and C, which each in turn return a superobject having to do
    with A, so why isn't A.met called twice still?
    >
    Thanks!

    Basically super(class_, self).method looks in self's mro (it's list of
    base classes) for class class_, and then starts searching *after* class
    class_ for the next class that implements the method.

    In this case the object's (instance of D) mro will be (D, B, C, A,
    object), so as super gets called in each class, it looks in that list
    (tuple, whatever) for the class following it (actually the next class
    following it that implements the method).

    Since no class appears in that list more than once, each class's
    implementation of the method will only be called once.


    HTH,
    ~Simon


    Also, if you haven't already, read:


    Comment

    • John Salerno

      #3
      Re: trouble understanding super()

      Simon Forman wrote:
      In this case the object's (instance of D) mro will be (D, B, C, A,
      object), so as super gets called in each class, it looks in that list
      (tuple, whatever) for the class following it (actually the next class
      following it that implements the method).
      >
      Since no class appears in that list more than once, each class's
      implementation of the method will only be called once.
      But after super(D, self).met() is called, doesn't that then call both
      super(B, self).met() and super(C, self).met()? If so, how does that
      avoid calling A.met twice? Or is that not what's happening?

      Here's what I think gets called, in order, after running D().met():

      print 'D.met'
      super(D, self).met()
      print 'B.met'
      super(B, self).met()
      print 'A.met'
      print 'C.met'
      super(C, self).met()
      print 'A.met'

      Comment

      • Duncan Booth

        #4
        Re: trouble understanding super()

        John Salerno wrote:
        But after super(D, self).met() is called, doesn't that then call both
        super(B, self).met() and super(C, self).met()? If so, how does that
        avoid calling A.met twice? Or is that not what's happening?
        If you have an instance of a B then super(B,self).m et() will call A.met(),
        but if self is actually an instance of a D, then super(B,self).m et()
        actually calls C.met().

        That is why super needs both the class and the instance: so it can jump
        sideways across the inheritance diamond instead of always passing calls to
        the base of the current class.

        Comment

        • John Salerno

          #5
          Re: trouble understanding super()

          Duncan Booth wrote:
          John Salerno wrote:
          >
          >But after super(D, self).met() is called, doesn't that then call both
          >super(B, self).met() and super(C, self).met()? If so, how does that
          >avoid calling A.met twice? Or is that not what's happening?
          >
          If you have an instance of a B then super(B,self).m et() will call A.met(),
          but if self is actually an instance of a D, then super(B,self).m et()
          actually calls C.met().
          >
          That is why super needs both the class and the instance: so it can jump
          sideways across the inheritance diamond instead of always passing calls to
          the base of the current class.
          Oh, I think I get it! So what's happening is this:

          1. the MRO in this case is always (D, B, C, A, object)
          2. super(D, self).met() looks in B
          3. super(B, self).met() looks in C
          4. super(C, self).met() looks in A

          Right? So it's like making a ladder? I guess my confusion came when I
          thought that a call to super(B, self).met() also called A.met, but I
          guess it stops at C and lets C call it.

          Comment

          Working...