面向物件(三)繼承和多型
阿新 • • 發佈:2021-12-09
繼承
什麼是繼承
繼承就是新建類的一種方式,新建的類我們稱為子類或者派生類,被繼承的類稱為父類或基類。
子類可以使用父類中的屬性或方法。
為什麼要使用繼承
類解決了物件和物件之間的程式碼冗餘問題。
繼承解決了類和類之間的程式碼冗餘問題。
如何使用繼承
在Python2中的子類存在區別:
新式類:繼承了object類的子子孫孫類都是新式類。
經典類:沒有繼承了object類的子子孫孫類都是經典類。
類的繼承
# 定義一個公共的類 class People: def __init__(self, name, age, gender): self.name= name self.age = age self.gender = gender # 定義一個People類的子類 class Student(People): def __init__(self, name, age, gender, course=None): if course is None: course = [] # 可使用父類中的屬性或方法 People.__init__(self, name, age, gender) self.course= course def choice_course(self, course): self.course.append(course) print('%s選課%s成功' % (self.name, self.course)) stu = Student('tom', 18, 'male', 'python') print(stu.name) # 結果為tom
屬性的查詢順序
單繼承下的屬性查詢順序
單繼承的情況下屬性的查詢是由子類一路向上查詢。
在查詢時要注意引數self指的一直是呼叫方法的屬性。
class Foo:def f1(self): print('Foo.f1') # 4.在Foo類中找到f2方法並執行 def f2(self): # 5.輸出Foo.f2 print('Foo.f2') # 6.此時的self指的是obj也就是Bar類 self.f1() # 3.在Bar類中找f2方法但沒找到 class Bar(Foo): # 7.執行Bar類的f1方法 def f1(self): # 8.輸出Bar.f1 print('Bar.f1') # 1.呼叫Bar類 obj = Bar() # 2.呼叫f2方法 obj.f2() # 結果: # Foo.f2 # Bar.f1
多繼承下的屬性查詢順序
經典類:按照深度優先的查詢順序。
在多繼承時,經典類會一次性查到底,然後才去第二個父類找。
新式類:按照廣度優先的查詢順序。
在多繼承時,新式類在查到繼承object類的父類時會先不查,直到沒有其他父類才會去查詢。
class A(object): def test(self): print('from A') class B(A): # def test(self): # print('from B') pass class C(A): # def test(self): # print('from C') pass class D(B): # def test(self): # print('from D') pass class E(C): # def test(self): # print('from E') pass class F(D, E): # def test(self): # print('from F') pass f1 = F() f1.test() # 經典類順序F->D->B->A->E->C # 新型類順序F->D->B->E->C->A查詢順序
super()和mro列表
super()方法提供了除了指名道姓外另一種從父類中呼叫屬性的方式。
# 定義一個公共的類 class People: def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender # 定義一個People類的子類 class Student(People): def __init__(self, name, age, gender, course=None): if course is None: course = [] # 可使用父類中的屬性或方法 # People.__init__(self, name, age, gender) # super()方法在Python2中相當於super(People,self) # 可直接將自己傳入,不用再寫self super().__init__(name, age, gender) self.course = course def choice_course(self, course): self.course.append(course) print('%s選課%s成功' % (self.name, self.course)) stu = Student('tom', 18, 'male', 'python') print(stu.name) # 結果為tom
super()方法的查詢順序是按照mor列表從左到右的順序進行查詢。
因此即使沒有明顯的繼承關係,使用super()方法依然可以找到。
class A: # 4.A中有text開始呼叫 def test(self): print('from A.test') # 5.super方法呼叫text,即使A並沒有父類,也會按照mor列表順序去B中找 super().test() class B: # 6.B中有text則呼叫 def test(self): print('from B') # 3.c中沒有先去父類A中找 class C(A, B): pass # 1.例項化c c = C() # 2.查詢text c.test() # 結果為 # from A.test # from B print(C.mro()) # 結果為[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>] # 因此super的查詢順序為C->A->B
多型和多型性
多型
多型指的是事物的不同形態。
在現實生活中:水的形態分為液態水、冰、水蒸氣。
在電腦中:檔案有多種形態:文字檔案,可執行檔案等。
多型性
多型性是指在不考慮例項型別的情況下使用例項。
好處是能增加檔案的靈活性和可擴充套件性。
import abc # 抽象類: 抽象類只能被繼承,不能被例項化 class Animal(metaclass=abc.ABCMeta): # 該方法已經是抽象方法瞭如果子類沒有對應方法會直接報錯 @abc.abstractmethod def speak(self): pass class People(Animal): def speak(self): print('嗷嗷嗷') class Pig(Animal): def speak(self): print('哼哼哼') class Dog(Animal): def speak(self): print('汪汪汪') obj = People() obj1 = Pig() obj2 = Dog() # 多型帶來的特性:在不用考慮物件資料型別的情況下,直接呼叫對應的函式 def animal(animal): return animal.speak() animal(obj) animal(obj1) animal(obj2) # 結果: # 嗷嗷嗷 # 哼哼哼 # 汪汪汪