探討 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 才能夠被繼承下來。