Question related to super() with __init__()

天涯浪子 提交于 2020-01-03 17:03:31

问题


Given 3 classes below,

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')

If I run D = C(), it will return

B
C

If I run print(C.__mro__), it will gives (<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>). I think that means class A will be executed as it is inside the mro list.However, this is not the case.

I want ask why .__init__() is necessary for A.__init__() happening.


回答1:


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__)

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'>)

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.




回答2:


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()

Because this is python behaviour. If you have A and B class and A is parent of B and B also has __init__ method, you should call A.__init__ manually. Otherwise, python will override it. You need explicit call !

We have __init__ in python (Something like constructor). You should call it manually in some cases. It's not called automatically as it's in other languages.



来源:https://stackoverflow.com/questions/56217501/question-related-to-super-with-init

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!