问题
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