multiple inheritance

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

    multiple inheritance

    i don't know how to call methods of super classes when using multiple
    inheritance. I've looked on the net but with no result :(

    class a(object):
    def foo(self):
    print "a"

    class b(object):
    def foo(self):
    print "a"

    class c(a,b)
    def foo(self):
    super( ???? a).foo()
    super( ???? b).foo()

    r = c()
    r.foo()

  • Andreas Kostyrka

    #2
    Re: multiple inheritance

    I'm sure it's documented somewhere, but here we go :)

    The correct usage is super(MyClass, self)

    The idea is that super allows for cooperative calls. It uses MyClass to locate
    what class "above" to call.

    This way you can something like that:

    class A(object):
    def bar(self):
    print "A"
    #getattr(super( A, self),"bar", lambda : None)()

    class B(object):
    def bar(self):
    print "B"
    #getattr(super( B, self),"bar", lambda : None)()

    class C(A,B):
    def bar(self):
    print "C"
    getattr(super(C , self),"bar", lambda : None)()

    print "-" * 20, "no super in A/B"
    C().bar()

    class A(object):
    def bar(self):
    print "A"
    getattr(super(A , self),"bar", lambda : None)()

    class B(object):
    def bar(self):
    print "B"
    getattr(super(B , self),"bar", lambda : None)()

    class C(A,B):
    def bar(self):
    print "C"
    getattr(super(C , self),"bar", lambda : None)()

    print "-" * 20, "protected getattr/super in A/B"

    C().bar()

    class base(object):
    def bar(self):
    print "base"

    class A(base):
    def bar(self):
    print "A"
    getattr(super(A , self), "bar", lambda : None)()

    class B(base):
    def bar(self):
    print "B"
    getattr(super(B , self), "bar", lambda : None)()

    class C(A,B):
    def bar(self):
    print "C"
    getattr(super(C , self), "bar", lambda : None)()

    print "-" * 20, "base class without super call"
    C().bar()

    This produces:
    -------------------- no super in A/B
    C
    A
    -------------------- protected getattr/super in A/B
    C
    A
    B
    -------------------- base class without super call
    C
    A
    B
    base

    Andreas
    On Thu, Jun 09, 2005 at 12:56:53AM -0700, newseater wrote:[color=blue]
    > i don't know how to call methods of super classes when using multiple
    > inheritance. I've looked on the net but with no result :(
    >
    > class a(object):
    > def foo(self):
    > print "a"
    >
    > class b(object):
    > def foo(self):
    > print "a"
    >
    > class c(a,b)
    > def foo(self):
    > super( ???? a).foo()
    > super( ???? b).foo()
    >
    > r = c()
    > r.foo()
    >
    > --
    > http://mail.python.org/mailman/listinfo/python-list[/color]

    Comment

    • newseater

      #3
      Re: multiple inheritance

      if I only use the super() construct it seems not to call B




      class A(object):
      def foo(self):
      print "a"

      class B(object):
      def foo(self):
      print "b"

      class C(A,B):
      def foo(self):
      print "c"
      super(C,self).f oo()


      c = C()

      produces
      c
      a




      oddly i can produce a "b" by using

      super(A,self).f oo()

      i'm not sure why it isn't super(B,self).f oo()

      Comment

      • Duncan Booth

        #4
        Re: multiple inheritance

        newseater wrote:
        [color=blue]
        > if I only use the super() construct it seems not to call B
        >
        >
        >
        >
        > class A(object):
        > def foo(self):
        > print "a"
        >
        > class B(object):
        > def foo(self):
        > print "b"
        >
        > class C(A,B):
        > def foo(self):
        > print "c"
        > super(C,self).f oo()
        >
        >
        > c = C()
        >
        > produces
        > c
        > a
        >
        >[/color]

        That is because a single call to super only calls a single method from one
        base class. Each call to super works out which is the next method that
        should be called and calls it, but it is then up to that method to ensure
        the call gets passed on along the chain.

        The problem with super is that you need to be sure to terminate that
        calling chain somehow. You can do what Andreas did, and use getattr to
        check for the existence of the base class method, but that gets messy. I
        find the easiest way is to define the interface in an abstract base class
        which deliberately doesn't pass the call upwards:

        class IFoo(object):
        def foo(self):
        pass

        class A(IFoo):
        def foo(self):
        print "a"
        super(A,self).f oo()

        class B(IFoo):
        def foo(self):
        print "b"
        super(B,self).f oo()

        class C(A,B):
        def foo(self):
        print "c"
        super(C,self).f oo()

        [color=blue][color=green][color=darkred]
        >>> A().foo()[/color][/color][/color]
        a[color=blue][color=green][color=darkred]
        >>> B().foo()[/color][/color][/color]
        b[color=blue][color=green][color=darkred]
        >>> C().foo()[/color][/color][/color]
        c
        a
        b[color=blue][color=green][color=darkred]
        >>>[/color][/color][/color]

        You can also ask a class the order in which its base classes are examine
        for methods:
        [color=blue][color=green][color=darkred]
        >>> C.mro()[/color][/color][/color]
        [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class
        '__main__.IFoo' >, <type 'object'>]

        This is how super works, 'super(A, self)' when self is a C returns an
        object which will look at self.__class__. mro(), which is the list above,
        finds the class A, and then searches the remaining classes for matching
        attributes (B, IFoo, then object). The same super call on an instance of A
        gets a shorter list which doesn't include B as a possible target:
        [color=blue][color=green][color=darkred]
        >>> A.mro()[/color][/color][/color]
        [<class '__main__.A'>, <class '__main__.IFoo' >, <type 'object'>]

        Comment

        • newseater

          #5
          Re: multiple inheritance

          how nice! is this due to a linearization taking place of A and B when
          compiling C ? is this a 'feature' of the language or its actual
          semantics to behave like this?

          [color=blue]
          > class IFoo(object):
          > def foo(self):
          > pass
          >
          > class A(IFoo):
          > def foo(self):
          > print "a"
          > super(A,self).f oo()
          >
          > class B(IFoo):
          > def foo(self):
          > print "b"
          > super(B,self).f oo()
          >
          > class C(A,B):
          > def foo(self):
          > print "c"
          > super(C,self).f oo()
          >[color=green][color=darkred]
          > >>> C().foo()[/color][/color]
          > c
          > a
          > b[/color]

          Comment

          • Michele Simionato

            #6
            Re: multiple inheritance

            If you are curious, the MRO algorithm is explained here:

            The official home of the Python Programming Language


            Michele Simionato

            Comment

            Working...