与具有__init __()的super()有关的问题

时间:2019-05-20 08:59:22

标签: python super

给出以下3个课程,

class A(object):
    def __init__(self):
        print('A')
    def test(self):
        print('1')

class B(A):
    def __init__(self):
        super(B,self)        ## if .__init__() is not given here
        print('B')

class C(B, A):
    def __init__(self):
        super(C, self).__init__()
        print('C')

如果我运行D = C(),它将返回

B
C

如果我运行print(C.__mro__), 它将得到(<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)。 我认为这意味着将在mro列表中执行类A。但是,事实并非如此。

我想问为什么.__init__()对于发生A.__init__()是必要的。

2 个答案:

答案 0 :(得分:7)

那不是不是是什么意思!

我认为您实际上对两件事感到困惑:mro是什么,以及Python中子类构造函数的性质。让我们先来看mro

mro的意思是“方法解析顺序”,并指定Python解释器查找适当命名的方法的顺序。

因此,假设您具有以下类层次结构:

class A:

    def deepest(self):
        print('I wonder where this is coming from...')

    def deeer(self):
        print('deeper from A')

    def deep(self):
        print('deep from A')

class B(A):

    def deeper(self):
        print('deeper from B')

    def deep(self):
        print('deep from B')

class C(B):

    def deep(self):
        print('deep from C')

c = C()
c.deep()
c.deeper()
c.deepest()
print(c.__mro__)

输出:

deep from C
deeper from B
I wonder where this is coming from...
(<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)

当我们调用deep时,Python在C中查找它,因为Cmro中是第一个。它找到了,不再走了。

另一方面,对于deeper,Python无法在C中找到它,因此转到层次结构中的下一个B并找到它。

deepest相同,只能在A中找到。

现在,我们将其连接到__init__

在这种情况下,当您从__init__调用super时,Python将在层次结构中查找第一个超类B,并调用其__init__方法。

但是,如果__init__的{​​{1}}方法没有调用B,则然后链就在那里停了

与其他语言不同,子类不会自动调用其超类的A.__init__方法,除非它们当然没有定义自己的__init__方法,否则就属于__init__ ,如上所述。

这符合Python的“我们都同意成年人在这里”的哲学-如果您不想调用超类的c.deeper(),那么可以这样做,但是后果自负。 / p>

答案 1 :(得分:1)

class A:

    def __init__(self):
        print('A.__init__()')

class B(A):

    def __init__(self):
        print('B.__init__()')
        super().__init__() # this will call A.__init__()
b = B()

因为这是python行为。如果您拥有AB类,并且AB的父级,并且B也具有__init__方法,则应调用{{1 }}。否则,python将覆盖它。您需要显式呼叫!

我们在python中有A.__init__(类似构造函数)。在某些情况下,您应该手动调用它。它不会像其他语言那样被自动调用。