super() 詳解
https://www.cnblogs.com/poloyy/p/15223443.html
多繼承中使用 super()
class A: def test(self): print("AAA") class B: def test(self): print("BBB") class C(A, B): def test(self): print("CCC") super().test() c = C() c.test() # 輸出結果 CCC AAA
根據 MRO,super() 很明顯調用的是 A 類的 test() 方法
假設想調用 B 類的 test() 方法,要怎么做呢?
方式
class C(A, B): def test(self): print("CCC") super().test() B.test(self) # 輸出結果 CCC AAA BBB
通過 父類名.方法名() 即可,但這樣和 super() 混用,不是一個好編碼習慣,具體看下面
混用super() 和 顯示類調用
class A: def __init__(self): print("A", end=" ") super().__init__() class B: def __init__(self): print("B", end=" ") super().__init__() class C(A, B): def __init__(self): print("C", end=" ") A.__init__(self) B.__init__(self) print("MRO:", [x.__name__ for x in C.__mro__]) C() # 輸出結果 MRO: ['C', 'A', 'B', 'object'] C A B B
B 類的 __init__() 方法被調用了兩次
為什么呢?
- C 類里面又通過 B.__init__() 顯式的調用了一次
- 從 MRO 可以看到,A 類后面跟的是 B 類,所以 A 類的 super() 會調用 B 類
- 一共調用了兩次
如何避免
- 在多繼承場景中,super() 的使用必須一致,即在類的層次結構中,要么全部使用 super(),要么全不用!堅決不混用
- 繼承父類時應該查看類的層次結構,就是使用類的 __mro__ 屬性,或者 mro() 方法查看相關類的 MRO
