关于python:多个继承如何处理super()和不同的 __init__() 参数?

How does multiple inheritance work with the super() and different __init__() arguments?

我只是在潜入一些更高级的Python主题(好吧,至少对我来说是高级的)。我现在正在阅读关于多重继承以及如何使用super()。我或多或少理解超级函数的使用方式,但是(1)这样做有什么问题?:

1
2
3
4
5
6
7
8
9
10
11
12
13
class First(object):
    def __init__(self):
        print"first"

class Second(object):
    def __init__(self):
        print"second"

class Third(First, Second):
    def __init__(self):
        First.__init__(self)
        Second.__init__(self)
        print"that's it"

关于super(),andrew kuchlings在python warts上的论文说:

usage of super() will also be correct when the Derived class inherits
from multiple base classes and some or all of them have init
methods

因此,我重写了上面的示例,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
class First(object):
    def __init__(self):
        print"first"

class Second(object):
    def __init__(self):
        print"second"

class Third(First, Second):
    def __init__(self):
        super(Third, self).__init__(self)
        print"that's it"

然而,这只运行它能找到的第一个in it,它在First中。(2)super()是否可以同时运行FirstSecond的init,如果可以,如何运行?运行super(Third, self).__init__(self)两次只运行first.init()两次。

增加一些混乱。如果继承类的init()函数采用不同的参数会怎么样?例如,如果我有这样的东西:

1
2
3
4
5
6
7
8
9
10
11
12
13
class First(object):
    def __init__(self, x):
        print"first"

class Second(object):
    def __init__(self, y, z):
        print"second"

class Third(First, Second):
    def __init__(self, x, y, z):
        First.__init__(self, x)
        Second.__init__(self, y, z)
        print"that's it"

(3)如何使用super()为不同继承类init函数提供相关参数?

欢迎使用所有提示!

另外,由于我有几个问题,我把它们加粗并编号。


对于问题2,您需要在每个类中调用super:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class First(object):
    def __init__(self):
        super(First, self).__init__()
        print"first"

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

class Third(First, Second):
    def __init__(self):
        super(Third, self).__init__()
        print"that's it"

对于问题3,这不可能做到,您的方法需要具有相同的签名。但是您可以忽略父类中的一些参数或使用关键字参数。


1)像你在1中所做的那样,没有什么错,如果你想使用基类的属性,那么你必须调用基类init(),或者即使你使用的是来自使用自己类属性的基类的方法,你也必须调用基类init()。

2)不能使用super从第一个和第二个运行init,因为python使用mro(方法解析顺序)

请参见以下代码这是菱形层次结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class A(object):
    def __init__(self):
        self.a = 'a'
        print self.a

class B(A):
    def __init__(self):
        self.b = 'b'
        print self.b

class C(A):
    def __init__(self):
        self.c = 'c'
        print self.c

class D(B,C):
    def __init__(self):
        self.d = 'd'
        print self.d
        super(D, self).__init__()

d = D()
print D.mro()

它打印:

1
2
3
d
b
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>]

python的mro是d,b,c,a

如果B没有init方法,它将指向C。

3)您不能这样做,所有方法都需要具有相同的签名。