探討 Python 的繼承關係 - tsungjung411/python-study GitHub Wiki
class A: def __init__(self): A.name = 'A.name' A.name1 = 'A.name1' A._name2 = 'A._name2' A.__name3 = 'A.__name3' self.name4 = 'a.name4' self._name5 = 'a._name5' self.__name6 = 'a.__name6' # end-of-def # end-of-class class B(A): def __init__(self): B.name = 'B.name' B.name1 = 'B.name1' B._name2 = 'B._name2' B.__name3 = 'B.__name3' self.name4 = 'b.name4' self._name5 = 'b._name5' self.__name6 = 'b._name6' # end-of-def def dump_b_info(self): print("super(B, self).name:", super(B,self).name) print("super(B, self).name1:", super(B,self).name1) print("super(B, self)._name2:", super(B,self)._name2) print("super(B, self).__name3: X (類別私有成員)") # error, 類別私有成員 print("super(B, self).name4: X (執行時期宣告,不能被繼承下來,因為它宣告在 self)") # error print("super(B, self)._name5: X (執行時期宣告,不能被繼承下來,因為它宣告在 self)") # error print("super(B, self).__name6: X (執行時期宣告,不能被繼承下來,因為它宣告在 self)") # error print() # end-of-def # end-of-class class C(B): def __init__(self): pass # end-of-def # end-of-class # ------------------------ # 測試 class & object # ------------------------ a = A() print("A.name:", a.name) print("A.name1:", a.name1) print("A._name2:", a._name2) print("A.__name3: X (類別私有成員)") # error, 類別私有成員 print("A.self.name4:", a.name4) print("A.self._name5:", a._name5) print("A.self.__name6: X (類別私有成員)") # error, 類別私有成員 print() b = B() b.dump_b_info() print("B.name:", b.name) print("B.name1:", b.name1) print("B._name2:", b._name2) print("B.__name3: X (類別私有成員)") # error, 類別私有成員 print("B.self.name4:", b.name4) print("B.self._name5:", b._name5) print("B.self.__name6: X (類別私有成員)") # error, 類別私有成員 print() c = C() print("dir(C): ", dir(C), end='\n\n') print("dir(c): ", dir(c), end='\n\n') print("C.name:", c.name) print("C.name1:", c.name1) print("C._name2:", c._name2) print("C.__name3: X (類別私有成員)") # error, 類別私有成員 print("C.self.name4: X (執行時期宣告,不能被繼承下來,因為它宣告在 self)") # error print("C.self._name5: X (執行時期宣告,不能被繼承下來,因為它宣告在 self)") # error print("C.self.__name6: X (執行時期宣告,不能被繼承下來,因為它宣告在 self)") # error
執行結果:
A.name: A.name A.name1: A.name1 A._name2: A._name2 A.__name3: X (類別私有成員) A.self.name4: a.name4 A.self._name5: a._name5 A.self.__name6: X (類別私有成員) super(B, self).name: A.name super(B, self).name1: A.name1 super(B, self)._name2: A._name2 super(B, self).__name3: X (類別私有成員) super(B, self).name4: X (執行時期宣告,不能被繼承下來,因為它宣告在 self) super(B, self)._name5: X (執行時期宣告,不能被繼承下來,因為它宣告在 self) super(B, self).__name6: X (執行時期宣告,不能被繼承下來,因為它宣告在 self) B.name: B.name B.name1: B.name1 B._name2: B._name2 B.__name3: X (類別私有成員) B.self.name4: b.name4 B.self._name5: b._name5 B.self.__name6: X (類別私有成員) dir(C): ['_A__name3', '_B__name3', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_name2', 'name', 'name1'] dir(c): ['_A__name3', '_B__name3', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_name2', 'name', 'name1'] C.name: B.name C.name1: B.name1 C._name2: B._name2 C.__name3: X (類別私有成員) C.self.name4: X (執行時期宣告,不能被繼承下來,因為它宣告在 self) C.self._name5: X (執行時期宣告,不能被繼承下來,因為它宣告在 self) C.self.__name6: X (執行時期宣告,不能被繼承下來,因為它宣告在 self)
說明:
- 宣告在 class 上,是屬於編譯時期(compile-time)宣告
- 宣告在 self 上,是屬於執行時期(run-time)宣告
- [補充] 有些語言宣告(declaration)是指「定義變數型別」,定義(definiation)是指「定義變數型別 + 初始化參數」,這邊的宣告單純指「定義物件成員」
- 可以看出,
__field
不管是宣告在 class 上, 還是 self 上,都無法存取。它是私有的,只有「宣告者」在自己的 class 內部可以存取。 - 宣告在 self 上,不管是
field
還是_field
,都無法被繼承下來的(因為屬性是 runtime 掛上去的,當然不會出現在子類別),只有需告在 class 才能夠被繼承下來。