Could somebody explain why this code prints Y and not X? I expected it to print “X” because it says pass in Class C and Class X is the next super class.
JavaScript
x
41
41
1
class X:
2
def foo(self):
3
return "X"
4
5
class Y:
6
def foo(self):
7
return "Y"
8
9
class A(X):
10
def foo(self):
11
return self.met()
12
13
class B(A):
14
def foo(self):
15
return "B"
16
17
class C(X):
18
pass
19
20
class D(C, X):
21
def met(self):
22
return "D"
23
24
class E(A, D):
25
def foo(self):
26
return super().foo()
27
28
class F(Y,B):
29
pass
30
31
class G(D, B):
32
pass
33
34
class H(E, A, X):
35
def met(self):
36
return "H"
37
38
class I(G,F):
39
pass
40
print(I().foo())
41
Sorry for the long code, but I dont know how to make it shorter without making the question unclear
Advertisement
Answer
Per Python Multiple Inheritance: The Diamond Rule
:
- List all the base classes, following the classic lookup rule and include a class multiple times if it’s visited repeatedly. In the above example, the list of visited classes is [D, B, A, C, A].
- Scan the list for duplicated classes. If any are found, remove all but one occurrence, leaving the last one in the list. In the above example, the list becomes [D, B, C, A] after dropping duplicates.
JavaScript
1
9
1
m = ['I', 'G', 'D', 'C', 'X', 'object', 'X', 'object', 'B', 'A',
2
'X', 'object', 'F', 'Y', 'object', 'B', 'A', 'X', 'object']
3
s = set()
4
custom_mro = [i for i in reversed(m) if not (i in s or s.add(i))][::-1]
5
original_mro = list(i.__name__ for i in I.__mro__)
6
7
assert custom_mro == original_mro
8
print(custom_mro) #['I', 'G', 'D', 'C', 'F', 'Y', 'B', 'A', 'X', 'object']
9
Y is printed because Y
class is listed first on the mro order.