Reputation: 35982
A B
| | | |
C D E F
| | | |
G H
|
I
user@ubuntu:~/Documents/Python/oop_python$ cat tt.py
class A:
def call_me(self):
print("A")
class C(A):
def call_me(self):
super().call_me()
print("C")
class D(A):
def call_me(self):
super().call_me()
print("D")
class B:
def call_me(self):
print("B")
class E(B):
def call_me(self):
super().call_me()
print("E")
class F(B):
def call_me(self):
super().call_me()
print("F")
class G(C, D, E):
def call_me(self):
super().call_me()
print("G")
class H(F):
def call_me(self):
super().call_me()
print("H")
class I(G, H):
def call_me(self):
super().call_me()
print("I")
user@ubuntu:~/Documents/Python/oop_python$ python3.2 -i tt.py
>>> i = I()
>>> i.call_me()
A
D
C
G
I
Question> Why B
, E
, F
are not printed?
// updated based on comments from delnan
user@ubuntu:~/Documents/Python/oop_python$ cat tt.py
class BaseClass():
def call_me(self):
print("BaseClass")
pass
class A(BaseClass):
def call_me(self):
super().call_me()
print("A")
class C(A):
def call_me(self):
super().call_me()
print("C")
class D(A):
def call_me(self):
super().call_me()
print("D")
class B(BaseClass):
def call_me(self):
super().call_me()
print("B")
class E(B):
def call_me(self):
super().call_me()
print("E")
class F(B):
def call_me(self):
super().call_me()
print("F")
class G(C, D, E):
def call_me(self):
super().call_me()
print("G")
class H(F):
def call_me(self):
super().call_me()
print("H")
class I(G, H):
def call_me(self):
super().call_me()
print("I")
user@ubuntu:~/Documents/Python/oop_python$ python3.2 -i tt.py
>>> i = I()
>>> i.call_me()
BaseClass
B
F
H
E
A
D
C
G
I
Upvotes: 5
Views: 3123
Reputation: 1856
The precondition to use super is the class must be the new-style.
A class hierarchy with single inheritance, super can use to refer to parent class without naming them explicitly
Second use case is support cooperative multiple inheritance in a dynamic execution environment.
So, the second case is matching your second example condition. In this case the subclass will do a bfs traverse to make sure each overwrite base class method is called only once. Your inheritance tree could be rewrite to liner as this order (follow the bfs traverse, left to right) I G C D A E H F B BaseClass.
Super(type[,object-or-type])
It will return a proxy object that delegates method calls to a parent or sibling class of type. In python 3.x you could call super() directly which is as same as super(currentClassName, self). This will get the proxy of the direct right super|sibling class generated by the bfs traverse. So the method i.call_me() will be called as:
I.call_me -> G.call_me -> C.call_me -> D.call_me -> A.call_me -> E.call_me -> H.call_me -> F.call_me -> B.call_me -> BaseClass.call_me
As you asked why the first example didn't print B, E, F, because the inheritance map is not a "diamond graph" which means the A.call_me B.call_me are different method. So python only choose one of the inheritance branch.
Wish this helpful. You could also check the python class doc for more detail
Upvotes: 1
Reputation: 172249
A common misunderstanding is that super() will call all superclasses methods. It will not. It will call only one of them. Which one is automatically calculated by super() according to some specific rules. Sometimes the one it calls is not an actual super-class, but a sibling. But there is no guarantee that all will be called, unless all of the classes in their turn are using super().
In this case, A and B is not calling super. And if you add it to A, it will in fact call the "missing" classes, but if you add it to B you get an error, because in this particular case, B will end up being the "last" (or first, depending on how you see it) class.
If you want to use super(), the best solution is to have a common baseclass for A and B that implements call_me, but does not call super(). (Thanks to delnan for suggesting that).
However, if you know your class hierarchy, you can call the superclasses methods directly instead of using super(). Note that this in the case above, doesn't mean that every class must call each of it's baseclasses directly. This is therefore not useful in cases where you as a programmer don't have complete control over the class hierarchy, for example if you write libraries or mixin-classes. Then you have to use super().
Upvotes: 7