在OOP(Object Oriented Programming)程序設計中,當咱們定義一個class的時候,能夠從某個現有的class 繼承,新的class稱爲子類(Subclass),而被繼承的class稱爲基類、父類或超類(Base class、Super class)。ide
咱們先來定義一個class Person,表示人,定義屬性變量 name 及 sex (姓名和性別);函數
定義一個方法print_title():當sex是male時,print man;當sex 是female時,print woman。參考以下代碼:spa
1 class Person(object): 2 def __init__(self,name,sex): 3 self.name = name 4 self.sex = sex 5 6 def print_title(self): 7 if self.sex == "male": 8 print("man") 9 elif self.sex == "female": 10 print("woman") 11 12 class Child(Person): # Child 繼承 Person 13 pass 14 15 May = Child("May","female") 16 Peter = Person("Peter","male") 17 18 print(May.name,May.sex,Peter.name,Peter.sex) # 子類繼承父類方法及屬性 19 May.print_title() 20 Peter.print_title()
而咱們編寫 Child 類,徹底能夠繼承 Person 類(Child 就是 Person);使用 class subclass_name(baseclass_name) 來表示繼承;設計
繼承有什麼好處?最大的好處是子類得到了父類的所有屬性及功能。以下 Child 類就能夠直接使用父類的 print_title() 方法code
實例化Child的時候,子類繼承了父類的構造函數,就須要提供父類Person要求的兩個屬性變量 name 及 sex:blog
在繼承關係中,若是一個實例的數據類型是某個子類,那它也能夠被看作是父類(May 既是 Child 又是 Person)。可是,反過來就不行(Peter 僅是 Person,而不是Child)。繼承
繼承還能夠一級一級地繼承下來,就比如從爺爺到爸爸、再到兒子這樣的關係。而任何類,最終均可以追溯到根類object,這些繼承關係看上去就像一顆倒着的樹。好比以下的繼承樹: it
Python 與其餘語言不一樣點在於,當咱們定義一個 class 的時候,咱們實際上就定義了一種數據類型。咱們定義的數據類型和Python自帶的數據類型,好比str、list、dict沒什麼兩樣。io
Python 有兩個判斷繼承的函數:isinstance() 用於檢查實例類型;issubclass() 用於檢查類繼承。參見下方示例:event
class Person(object): pass class Child(Person): # Child 繼承 Person pass May = Child() Peter = Person() print(isinstance(May,Child)) # True print(isinstance(May,Person)) # True print(isinstance(Peter,Child)) # False print(isinstance(Peter,Person)) # True print(issubclass(Child,Person)) # True
在說明多態是什麼以前,咱們在 Child 類中重寫 print_title() 方法:若爲male,print boy;若爲female,print girl
1 class Person(object): 2 def __init__(self,name,sex): 3 self.name = name 4 self.sex = sex 5 6 def print_title(self): 7 if self.sex == "male": 8 print("man") 9 elif self.sex == "female": 10 print("woman") 11 12 class Child(Person): # Child 繼承 Person 13 def print_title(self): 14 if self.sex == "male": 15 print("boy") 16 elif self.sex == "female": 17 print("girl") 18 19 May = Child("May","female") 20 Peter = Person("Peter","male") 21 22 print(May.name,May.sex,Peter.name,Peter.sex) 23 May.print_title() 24 Peter.print_title()
當子類和父類都存在相同的 print_title()方法時,子類的 print_title() 覆蓋了父類的 print_title(),在代碼運行時,會調用子類的 print_title()
這樣,咱們就得到了繼承的另外一個好處:多態。
多態的好處就是,當咱們須要傳入更多的子類,例如新增 Teenagers、Grownups 等時,咱們只須要繼承 Person 類型就能夠了,而print_title()方法既能夠直不重寫(即便用Person的),也能夠重寫一個特有的。這就是多態的意思。調用方只管調用,無論細節,而當咱們新增一種Person的子類時,只要確保新方法編寫正確,而不用管原來的代碼。這就是著名的「開閉」原則:
子類能夠沒有構造函數,表示同父類構造一致;子類也可重寫構造函數;如今,咱們須要在子類 Child 中新增兩個屬性變量:mother 和 father,咱們能夠構造以下(建議子類調用父類的構造方法,參見後續代碼):
1 class Person(object): 2 def __init__(self,name,sex): 3 self.name = name 4 self.sex = sex 5 6 class Child(Person): # Child 繼承 Person 7 def __init__(self,name,sex,mother,father): 8 self.name = name 9 self.sex = sex 10 self.mother = mother 11 self.father = father 12 13 May = Child("May","female","April","June") 14 print(May.name,May.sex,May.mother,May.father)
若父類構造函數包含不少屬性,子類僅需新增一、2個,會有很多冗餘的代碼,這邊,子類可對父類的構造方法進行調用,參考以下:
1 class Person(object): 2 def __init__(self,name,sex): 3 self.name = name 4 self.sex = sex 5 6 class Child(Person): # Child 繼承 Person 7 def __init__(self,name,sex,mother,father): 8 Person.__init__(self,name,sex) # 子類對父類的構造方法的調用 9 self.mother = mother 10 self.father = father 11 12 May = Child("May","female","April","June") 13 print(May.name,May.sex,May.mother,May.father)
多重繼承的概念應該比較好理解,好比如今須要新建一個類 baby 繼承 Child , 可繼承父類及父類上層類的屬性及方法,優先使用層類近的方法,代碼參考以下:
1 class Person(object): 2 def __init__(self,name,sex): 3 self.name = name 4 self.sex = sex 5 6 def print_title(self): 7 if self.sex == "male": 8 print("man") 9 elif self.sex == "female": 10 print("woman") 11 12 class Child(Person): 13 pass 14 15 class Baby(Child): 16 pass 17 18 May = Baby("May","female") # 繼承上上層父類的屬性 19 print(May.name,May.sex) 20 May.print_title() # 可以使用上上層父類的方法 21 22 23 class Child(Person): 24 def print_title(self): 25 if self.sex == "male": 26 print("boy") 27 elif self.sex == "female": 28 print("girl") 29 30 class Baby(Child): 31 pass 32 33 May = Baby("May","female") 34 May.print_title() # 優先使用上層類的方法