淺談Python中的繼承
繼承
Python 中所有的類都是object類的子類,而object 繼承自type
繼承分為 介面繼承和實現繼承
介面繼承:使用父類的介面名,子類重寫這個方法。儘可能的繼承介面類,在子類中實現方法,鼓勵對介面類的多繼承,這樣遵循介面隔離原則,有利於歸一化設計,不提倡對抽象類進行多繼承
實現繼承:子類不需要實現任何東西,直接使用父類介面和實現會增強程式碼的耦合性,不推薦使用。
一些細節
類繼承最終要被例項化,我們多數時候使用的還是物件而不是類。因此我們還是來一點點看繼~
繼承的過程
承僅僅是一種程式碼複用的手段,並不會講程式碼全部的載入到子類的空間中,方法依然屬於父類。下面的例子能看到,Cat.func 依然是 Animal 的,更近一步的理解,func 也僅僅是func,它只是被繫結到了類 Animal上而已,類 只是能幫我們找到這個函式,子類通過父類找到這個函式就完了~ 。
class Animal(object): def func(self): print("Animal.func") class Dog(Animal): def func(self): print('Dog.func') class Cat(Animal): """ No func~ """ print(Animal.func) # <function Animal.func at 0x103f79620> print(Cat.func) # <function Animal.func at 0x103f79620> print(Dog.func) # <function Dog.func at 0x104073510>
例項化的過程
例項化過程中屬性和方法並不會出現在例項的空間裡。它們依然屬於類本身,物件也只是能找到他們,然後呼叫他們。但是當修改物件的屬性時,會在物件的空間中建立同名的屬性。這是屬於物件的屬性。複雜的繼承其本質也是一樣的。
class Animal(object): def tell(self): print('self.name:%s Animal.name %s ' % (id(self.name),id(Animal.name))) name = 'Animal' class Cat(Animal): """ No func~ """ def tell(self): super().tell() print('self.name %s Cat.name %s '% (id(self.name),id(Cat.name))) cat = Cat() cat.tell() cat.name = 'django' cat.tell() # self.name:4473398472 Animal.name 4473398472 # self.name 4473398472 Cat.name 4473398472 # self.name:4474859736 Animal.name 4473398472 # self.name 4474859736 Cat.name 4473398472
單繼承
越靠近本類的方法會覆蓋祖輩的方法,這叫方法的覆蓋或重寫 原理是 Python的屬性檢索機制 從內層名稱空間往外查詢
class MyClass(object): """ A simple example class """ MyClassName = 'MyClass' name = 'MyClass' def func(self): print("This is {}".format(self.__class__.name)) def get_name(self): print(self.name) class MySonClass(MyClass): MySonClass = 'MySonClass' name = 'MySonClass' # 屬性的重寫 def get_name(self): super().get_name() print('我重寫了父類的get_name方法,上面是父類的方法,我來自子類!') person1 = MyClass() person2 = MySonClass() person1.func() person2.func() # 方法的實現繼承 自己沒有,會直接呼叫父類的方法。但是使用的屬性還是自己的。 print('*'*40) person1.get_name() person2.get_name() # 方法的介面繼承,在子類中重寫了這個方法。 # 結果 #------------------------------ # This is MyClass # This is MySonClass # **************************************** # MyClass # MySonClass # 我重寫了父類的get_name方法,上面是父類的方法,我來自子類!
多繼承
就形式上來說,類的繼承列表可以是一個,也可以是多個,當繼承列表只有一個類時,也就是隻有一個父類時,稱為單繼承,大於一個類,就稱為多繼承。
新式類的繼承方式為 廣度優先繼承 經典類的繼承方式為 深度優先繼承。
類繼承的順序可以使用類的 __mro__ 方法檢視。
鑽石繼承
class A(object): m = 'a' class B(A): m = 'b' class C(A): m = 'c' class D(B,C): # m = 'd' pass x = D() print(x.m) # D 的例項化物件如果獲取 m 屬性會優先的尋找自己的名稱空間,查詢順序為 D -> B -> C -> A
super()方法
語法super(類,例項化物件).父類的方法
當super()方法在類的內部使用時候,甚至不需要任何的引數
當在多繼承中使用super()方法的時候執行的不再是父類的方法了 而是和mro中上一級的方法
super()為了解決多繼承中,初始化方法被重複呼叫的問題。(當使用類名.方法名的時候)
當使用super()方法執行“父類” (__mro__ 方法的上一個類) 的方法
# 鑽石繼承中的 重複呼叫問題 # 注意 繼承的查詢順序~ 使用super()將按照 mro 順序執行 class Grand(object): def __init__(self,name): self.name = name print("class Grand ") class SonLeft(Grand): def __init__(self,age,name): self.age = age Grand.__init__(self,name) # 註釋調 跑一跑 看一看 # super().__init__(age,name) print("class SonLeft") class SonRight(Grand): def __init__(self,gender,name): self.gender = gender Grand.__init__(self,name) # 註釋調 跑一跑 看一看 # super().__init__(name) print("class SonRight") class GrandSon(SonLeft,SonRight): def __init__(self,name,gender): # super().__init__(age,name) SonLeft.__init__(self,name) # 註釋調 跑一跑 看一看 SonRight.__init__(self,name) # 註釋調 跑一跑 看一看 self.gender = gender grand_son = GrandSon("Monkey",18,"男")
以上就是淺談Python中的繼承的詳細內容,更多關於Python 繼承的資料請關注我們其它相關文章!