Python Call Parent Method Multiple Inheritance

前端 未结 3 983
一个人的身影
一个人的身影 2021-01-04 04:40

So, i have a situation like this.

class A(object):
    def foo(self, call_from):
        print \"foo from A, call from %s\" % call_from


class B(object):
           


        
相关标签:
3条回答
  • 2021-01-04 04:43

    You can use __bases__ like this

    class D(A, B, C):
        def foo(self):
            print("foo from D")
            for cls in D.__bases__:
                cls().foo("D")
    

    With this change, the output will be

    foo from D
    foo from A, call from D
    foo from B, call from D
    foo from C, call from D
    
    0 讨论(0)
  • 2021-01-04 04:46

    Add super() call's in other classes as well except C. Since D's MRO is

    >>> D.__mro__
    (<class '__main__.D'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <type 'object'>)
    

    You don't need super call in C.

    Code:

    class A(object):
        def foo(self, call_from):
            print "foo from A, call from %s" % call_from
            super(A,self).foo('A')
    
    class B(object):
        def foo(self, call_from):
            print "foo from B, call from %s" % call_from
            super(B, self).foo('B')
    
    
    class C(object):
        def foo(self, call_from):
            print "foo from C, call from %s" % call_from
    
    class D(A, B, C):
        def foo(self):
            print "foo from D"
            super(D, self).foo("D")
    
    d = D()
    d.foo()
    

    Output:

    foo from D
    foo from A, call from D
    foo from B, call from A
    foo from C, call from B
    
    0 讨论(0)
  • 2021-01-04 04:52

    I believe the call to super in sub-classes is the more Pythonic approach. One doesn't have to use the parent class names (particularly in super). Elaborating on the previous example, here's some code that should work (python 3.6+):

    class A:
        def foo(self, call_from):
            print(f"foo from A, call from {call_from}")
            super().foo('A')
    
    class B:
        def foo(self, call_from):
            print(f"foo from B, call from {call_from}")
            super().foo('B')
    
    
    class C(object):
        def foo(self, call_from):
            print(f"foo from C, call from {call_from}")
            super().foo('C')
    
    class StopFoo:
        def foo(self, call_from):
            pass
    
    class D(A, B, C, StopFoo):
        def foo(self, call_from):
            print(f"foo from D, call from {call_from}")
            super().foo('D')
    

    If you run this code:

    d = D()
    d.foo('D')
    

    You will get:

    foo from D, call from D
    foo from A, call from D
    foo from B, call from A
    foo from C, call from B
    

    The advantage of this strategy is you don't have to bother about the inheritance order, AS LONG as you include the StopFoo class. This one is a bit peculiar and might not be the best strategy to accomplish this task. Basically, every class in the inheritance tree calls the foo method and calls the parent method, which does the same. We might be talking about multiple inheritance, but an inheritance tree is actually flat (D -> A -> B -> C -> Stopfoo -> object). We can change the order of inheritance, add new classes to this pattern, remove them, just call one class... but the trick remains: include StopFoo before the call to foo leaves the class we have defined.

    For a mixin pattern with hooks, this might make sense. But of course, the solution isn't that useful in every case either. Don't fear super though, it has many tricks and can be useful in simple and multiple inheritance, with mixins or simple abstract classes.

    0 讨论(0)
提交回复
热议问题