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

Kel*_*vin 4 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')
Run Code Online (Sandbox Code Playgroud)

如果我跑步D = C(),它将返回

B
C
Run Code Online (Sandbox Code Playgroud)

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

我想问为什么.__init__()A.__init__()发生这种情况。

gmd*_*mds 7

That is not what it means!

I think you are actually confused about two things: what mro is, and the nature of subclass constructors in Python. Let's look at mro first.

mro means "method resolution order", and specifies the order in which the Python interpreter will look for appropriately named methods.

So, say you have the following class hierarchy:

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__)
Run Code Online (Sandbox Code Playgroud)

Output:

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

When we call deep, Python looks for it in C, since C is first in the mro. It finds it and goes no further.

On the other hand, for deeper, Python cannot find it in C and therefore goes to the next one in the hierarchy, which is B, and finds it.

Same thing for deepest, which is only found in A.

Now, let's connect this to __init__.

In this case, when you call __init__ from super, Python looks for the first superclass in the hierarchy, which is B, and calls its __init__ method.

However, if the __init__ method of B does not call A.__init__, then the chain stops there!

Unlike other languages, subclasses do not automatically call the __init__ method of their superclasses, unless of course they have not defined their own __init__ methods, then it is a case of c.deeper(), as above.

This is in line with Python's philosophy of "we're all consenting adults here" - if you don't want to call the superclass's __init__, then sure, do it, but you bear the consequences.