Python面向物件三大特徵之繼承
我們都知道Python面向物件程式設計有三大特徵,繼承,封裝和多型,下面幾篇問題,我們會分別講述著幾大特徵。
今天說的是繼承,如果有程式設計基礎的人對這個詞應該不會陌生,繼承是一種建立新類的方式,新建的類可以繼承一個或多個父類(python支援多繼承),父類又可稱為基類或超類,新建的類稱為派生類或子類,而子類會“”遺傳”父類的屬性(資料屬性和函式屬性),從而解決程式碼重用問題。
上面這段話就是繼承的概念和使用繼承所要達到的目的。
下面我們來看看具體程式碼案例,繼續的大致寫法就是
子類名(父類1,父類2,。。。)
Python是可以實現對繼承的,有些程式設計語法是隻能單繼承。
class ParentClass: name= '父類' def __init__(self,size,color): self.size = size self.color = color def fun(self): print('我來自父類') class SubClass(ParentClass): name = '子類' pass #例項化物件 s1 = SubClass('30','red') #{'size': '30', 'color': 'red'} 如果子類沒有構造方法的話,子類屬性會找到父類的構造方法,繼承父類的資料屬性 print(s1.__dict__) #(<class 'object'>,) python3中統一都是新式類,所以如果不加繼承的父類,預設的父類是object類 print(ParentClass.__bases__) #(<class '__main__.ParentClass'>,) 子類的父類 print(SubClass.__bases__) # "我來自父類" 子類物件呼叫父類的方法 s1.fun() #子類物件呼叫資料屬性,會先在子類中找,如果找不到會去父類的作用域裡面找 #這裡子類裡面定義了name屬性所以結果是: 子類 #如果子類裡面沒有定name,結果就是:父類 print(s1.name)
這段是繼承大致的用法,子類可以繼承父類的資料屬性和函式屬性。下面我們說說使用繼承的好處及程式碼重用和重寫,組合的用法
Python學習交流群:556370268,這裡是python學習者聚集地,有大牛答疑,有資源共享!有想學習python程式設計的,或是轉行,或是大學生,還有工作中想提升自己能力的,正在學習的小夥伴歡迎加入學習。
程式碼重用
我們現在有2個類貓和狗,它們都是動物,那如果我們要描述貓和狗這2個類的話,我們會存在大量的重複程式碼,如下
class Cat: def cry(self): print('喵喵') def eat(self): print('吃') def run(self): print('跑') def jump(self): print('跳') class Dog: def cry(self): print('汪汪') def eat(self): print('吃') def run(self): print('跑') def jump(self): print('跳') cat1 = Cat() dog1 = Dog() cat1.cry() dog1.cry()
上面2個類也許除了cry方法,其他的方法都是一樣的,都貓和狗同意的動作,那像上面那樣寫,就會出現大量的重複程式碼,下面我們用繼承來改寫
class animal: def cry(self): print('動物叫') def eat(self): print('吃') def run(self): print('跑') def jump(self): print('跳') class Cat(animal): def cry(self): print('喵喵') class Dog(animal): def cry(self): print('汪汪') cat1 = Cat() dog1 = Dog() cat1.cry() #喵喵 dog1.cry() #汪汪 cat1.eat() #吃 dog1.eat() #吃
上面我們定義了一個animal的父類,把子類的相同部分放入父類,子類就可以用繼承的方式來呼叫父類的函式屬性或者說方法了,而不用再類裡面再重複編碼。
Python學習交流群:556370268,這裡是python學習者聚集地,有大牛答疑,有資源共享!有想學習python程式設計的,或是轉行,或是大學生,還有工作中想提升自己能力的,正在學習的小夥伴歡迎加入學習。
類的方法重寫
其實上面的例子我們已經用到重寫,就是父類定義了一個方法,但是子類和父類的方法實現不一樣,要達到另外一個功能,比較上面
父類的cry方法時: ‘動物叫’
子類Cat的cry要實現:‘喵喵叫’
子類Dog的cry要實現:‘汪汪叫’
這種情況就要使用重寫
class animal: def cry(self): print('動物叫') def eat(self): print('吃') def run(self): print('跑') def jump(self): print('跳') class Cat(animal): def cry(self): print('喵喵') class Dog(animal): def cry(self): print('汪汪') cat1 = Cat() dog1 = Dog() cat1.cry() #喵喵 重寫父類cry方法 dog1.cry() #汪汪 重寫父類cry方法 子類的方法派生,就是子類可以定義自己的方法 class animal: def cry(self): print('動物叫') def eat(self): print('吃') def run(self): print('跑') def jump(self): print('跳') class Cat(animal): def cry(self): print('喵喵') def swoop(self): #定義子類的方法 print('飛撲') cat1 = Cat() cat1.swoop()
4.類的組合,組合指的是,在一個類中以另外一個類的物件作為資料屬性,稱為類的組合,當類之間有顯著不同,並且較小的類是較大的類所需要的元件時,用組合比較好.
class School: def __init__(self,name,addr): self.name=name self.addr=addr def recruit(self): print('%s xxx計算機學校正在招生' %self.name) class Course: def __init__(self,name,price,period,School): self.name=name self.price=price self.period=period self.school=School #實現Course和School的組合 s1=School('xxx計算機學校','北京') s2=School('xxx計算機學校','南京') s3=School('xxx計算機學校','上海') msg=''' 1 xxx計算機學校 北京校區 2 xxx計算機學校 南京校區 3 xxx計算機學校 上海校區 ''' while True: print(msg) menu={ '1':s1, '2':s2, '3':s3 } choice=input('選擇學校>>: ') school_obj=menu[choice] name=input('課程名>>: ') price=input('課程費用>>: ') period=input('課程週期>>: ') new_course=Course(name,price,period,school_obj) print('課程【%s】屬於【%s】學校' %(new_course.name,new_course.school.name)) #實現Course和School的組合
5.Python實現介面
介面就是定義抽象函式,不做具體函式實現,起到規範子類的作用,讓子類必須實現介面的抽象函式。介面提取了一群類共同的函式,可以把介面當做一個函式的集合。然後讓子類去實現介面中的函式。這麼做的意義在於歸一化,什麼叫歸一化,就是隻要是基於同一個介面實現的類,那麼所有的這些類產生的物件在使用時,從用法上來說都一樣。
歸一化的好處在於:
歸一化讓使用者無需關心物件的類是什麼,只需要的知道這些物件都具備某些功能就可以了,這極大地降低了使用者的使用難度。
歸一化使得高層的外部使用者可以不加區分的處理所有介面相容的物件集合
下面上程式碼
import abc #利用abc模組實現抽象類 class Interface(metaclass=abc.ABCMeta): @abc.abstractclassmethod #抽象方法,不做具體實現 def test1(self): pass @abc.abstractclassmethod def test2(self): pass class SubClass(Interface): def test1(self): print('實現抽象方法1') def test2(self): print('實現抽象方法2') s1 = SubClass()
如果我們子類裡面不實現具體的抽象函式,會報錯
import abc #利用abc模組實現抽象類 class Interface(metaclass=abc.ABCMeta): @abc.abstractclassmethod #抽象方法,不做具體實現 def test1(self): pass @abc.abstractclassmethod def test2(self): pass class SubClass(Interface): def test1(self): print('實現抽象方法1') #不實現test2方法 s1 = SubClass() 報錯資訊: Traceback (most recent call last): File "C:/Users/aryin/Desktop/mysite2/繼承.py", line 16, in s1 = SubClass() TypeError: Can't instantiate abstract class SubClass with abstract methods test2
6.類繼承的順序,根據類的MRO屬性
class A: def test(self): print('A') class B(A): def test(self): print('B') class C(A): def test(self): print('C') class D(B): def test(self): print('D') class E(C): def test(self): print('E') class F(D,E): def test(self): print('F') # (<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>) print(F.__mro__)
類繼承是是按照MRO屬性裡面的順序去呼叫父類的屬性
7.子類呼叫父類的方法,是通過super函式來實現的,在複雜的類繼承關係中,super()的取值是按照上面的MRO裡面的順序來定的。
class animal: def __init__(self,name,type,size,color): self.name = name self.type = type self.size = size self.color = color def cry(self): print('動物叫') def eat(self): print('吃') class Cat(animal): def __init__(self,name,type,size,color,age): super().__init__(name,type,size,color) #呼叫父類的建構函式,這是super最常用的地方 self.age = age def cry(self): super().cry() #子類重新了父類的方法,但是同時又要實現父類中cry方法 print('喵喵') cat1 = Cat('毛球','波斯貓',10,'白色','5歲') # 動物叫 # 喵喵 cat1.cry()