super() cho phép gọi phương thức của lớp cha trong đa kế thừa, tuân theo MRO (Method Resolution Order).
Đa kế thừa (Multiple Inheritance)
Một lớp con kế thừa từ nhiều lớp cha.
Ví dụ không dùng super()
class Father:
fathername = ""
def father(self):
print(self.fathername)
class Mother:
mothername = ""
def mother(self):
print(self.mothername)
class Child(Father, Mother):
def parent(self):
print("Father:", self.fathername)
print("Mother:", self.mothername)
s1 = Child()
s1.fathername = "Srinivas"
s1.mothername = "Anjali"
s1.parent()
Father: Srinivas Mother: Anjali
Ví dụ dùng super()
class Father:
def __init__(self):
self.fathername = ""
print("Father __init__")
class Mother:
def __init__(self):
self.mothername = ""
print("Mother __init__")
class Child(Father, Mother):
def __init__(self):
super().__init__() # Gọi Father.__init__ theo MRO
print("Child __init__")
s1 = Child()
s1.fathername = "Srinivas"
s1.mothername = "Anjali"
print("Father:", s1.fathername)
print("Mother:", s1.mothername)
Father __init__ Child __init__ Father: Srinivas Mother: Anjali
MRO (Method Resolution Order)
Python dùng thuật toán C3 Linearization để xác định thứ tự tìm kiếm phương thức. Xem MRO của class:
print(Child.__mro__)
(, , , )
super().__init__() trong Child gọi Father.__init__ (lớp cha đầu tiên trong MRO). Nếu Father cũng dùng super(), nó sẽ gọi Mother.__init__.
Diamond Problem (Kế thừa kim cương)
class A:
def __init__(self):
print("A")
super().__init__()
class B(A):
def __init__(self):
print("B")
super().__init__()
class C(A):
def __init__(self):
print("C")
super().__init__()
class D(B, C):
def __init__(self):
print("D")
super().__init__()
D()
D B C A
MRO của D: D -> B -> C -> A -> object. Mỗi __init__ được gọi đúng 1 lần nhờ super().
Best Practice
- Luôn dùng
super()trong__init__khi có kế thừa. - Không gọi trực tiếp
Father.__init__(self)(hardcoded) trừ khi cần thiết. - Hiểu MRO để tránh bug khó tìm.