简体   繁体   中英

python3 - behaviour of super() on multi-inheritance

I know that super() and multi-inheritance have already been discussed here. But I did not find a solution, regarding my specific problem in python3. Let's assume we have:

#! /usr/bin/env python3

class A(object):
    def __init__(self):
        super().__init__()

    def foo(self):
        print("The")

class B(object):
    def __init__(self):
        super().__init__()

    def foo(self):
        print("world")

class C(B):
    def __init__(self):
        super().__init__()

    def foo(self):
        super().foo()
        print("is")

class D(A,C):
    def __init__(self):
        super().__init__()

    def foo(self):
        super().foo()
        print("nice")

d = D()

d.foo()

This will get me:

The
nice

On the other hand, if I change the order of inheritance in D() to:

class D(C,A):
    def __init__(self):
        super().__init__()

    def foo(self):
        super().foo()
        print("nice")

It gives me

world
is
nice

I, however, only get the desired output:

The
world
is
nice

using:

class D(C,A):
    def __init__(self):
        super().__init__()

    def foo(self):
        A.foo(self)
        C.foo(self)
        print("nice")

Which I find quite unelegant.

So my question is: Is it possible to use super() in python3 invoking the super method of both super classes instead of just the first?

Unfortunately, without a knowledge of the method resolution order (MRO) of D , there is no way to call super() in D to get at both base classes.

But the MRO is powerful concept. In the second case,

class D(C,A):
    ...

the (MRO) is

>>> D.mro()
[<class '__main__.D'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]

Inasmuch as calling super() takes you to the next class in the MRO, as Mr. Pieters stated, and you want the print statements coming in the order of A , B , C , then D , simply put super().foo() first and print(...) second in each definition of foo() . The only exception is do not put super().foo() in class A because foo() is not defined in object .

Solution

#! /usr/bin/env python3

class A(object):
    def __init__(self):
        super().__init__()

    def foo(self):
        print("The")

class B(object):
    def __init__(self):
        super().__init__()

    def foo(self):
        super().foo()      # Inserted
        print("world")

class C(B):
    def __init__(self):
        super().__init__()

    def foo(self):
        super().foo()
        print("is")

class D(C,A):              # Correct ordering
    def __init__(self):
        super().__init__()

    def foo(self):
        super().foo()
        print("nice")

d = D()

d.foo()

Alternate solution

The MRO of D(A,C) in the first case includes all classes as well, so with correct ordering of super() and print(...) statements, one can make it work:

class A(object):
    def foo(self):
        print("The")
        super().foo()

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

class C(B):
    def foo(self):
        super().foo()
        print("is")

class D(A,C):
    def foo(self):
        super().foo()
        print("nice")

D().foo()

Further reading

To understand inheritance order (eg class D(C,A) or class D(A,C) ) and MRO, see https://www.python.org/download/releases/2.3/mro/ . The C3 method resolution order is described in detail and there are nicely drawn ASCII class hierarchies with the MRO labeled.

Maybe this will help

 class A(object):
    def __init__(self):
        super().__init__()

    def foo(self):
        print("The")
        if hasattr(super(), 'foo'):
            super().foo()

class B(object):
    def __init__(self):
        super().__init__()

    def foo(self):
        print("world")

class C(B):
    def __init__(self):
        super().__init__()

    def foo(self):
        super().foo()
        print("is")

class D(A,C):
    def __init__(self):
        super().__init__()

    def foo(self):
        super().foo()
        print("nice")

d = D()

d.foo()

output:

The
world
is
nice

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM