1. 程式人生 > >python面向物件---03-繼承、多繼承、super

python面向物件---03-繼承、多繼承、super

python面向物件—03-繼承、多繼承、super

階段一:繼承

情景模式:假設你正在參與一個魔幻類角色遊戲的開發,公司需要你為這個遊戲設計兩個角色的類:

  1. 劍士

    • 具有如下屬性:

      • 角色名
      • 角色等級
      • 生命值
      • 攻擊力
    • 具有如下行為:

      • 物理攻擊
  2. 法師

    • 具有如下屬性:

      • 角色名
      • 角色等級
      • 生命值
      • 攻擊力
    • 具有如下行為:

      • 物理攻擊

程式碼實現:

英勇的劍士:

class SwordsMan:
    def __init__(self, name, level, blood, attack_power):
        '''
        :param name:角色姓名
        :param level:角色等級
        :param blood:角色血量
        '''
self.name = name self.level = level self.blood = blood self.power = attack_power def fight(self): #角色攻擊行為 print('物理攻擊') def __str__(self): return "{clc}({name},{level},{blood})".format(clc = self.__class__.__name__, name = self.name, level = self.level, blood = self.blood)

智慧的法師:

class Magician:
    def __init__(self, name, level, blood, magic_power):
        '''
        :param name:角色姓名
        :param level:角色等級
        :param blood:角色血量
        '''
        self.name = name
        self.level = level
        self.blood = blood
        self.power = magic_power
    def
fight(self):
#角色攻擊行為 print('魔法攻擊') def __str__(self): return "{clc}({name},{level},{blood})".format(clc = self.__class__.__name__, name = self.name, level = self.level, blood = self.blood)

繼承 問題引入

問題一: 兩個中有大量重複的程式碼,是否能夠只寫一次 ?

  • 抽象出一個更抽象的類,放公共程式碼

問題二: 繼承的意義是什麼 ?

  • 重用程式碼,方便程式碼的管理和修改

問題三: 繼承是複製變數空間嘛 ?

  • 繼承不是變數空間複製
分類關係圖
這裡寫圖片描述

對以上連個角色進行進一步抽象,定義一個更加抽象的類— 角色類

程式碼如下:

class Rloe:
    def __init__(self,name,level,blood):
        '''
        :param name:角色姓名
        :param level:角色等級
        :param blood:角色血量
        '''
        self.name = name
        self.level =level
        self.blood = blood

    def __str__(self):
        return "{clc}({name},{level},{blood})".format(clc = self.__class__.__name__,
                                                      name = self.name,
                                                      level = self.level,
                                                      blood = self.blood)

    def fight(self):  # 角色攻擊行為
        raise NotImplementedError('必須在子類中實現該行為')   

繼承關係圖

這裡寫圖片描述

再從角色類中派生具體的類

注意:(派生與繼承是一個意思的兩個說法)

派生出的劍士:

class SwordsMan(Rloe):     #繼承自Role
    def __init__(self,name,level,blood,attack_power):
        '''
        :param name:角色姓名
        :param level:角色等級
        :param blood:角色血量
        '''
        Rloe.__init__(self,name,level,blood)
        self.attack_power = attack_power
    def fight(self):   #角色攻擊行為
        print('物理攻擊')

派生出的法師:

class Magician:        #繼承自Role
    def __init__(self,name,level,blood,magic_power):
        '''
        :param name:角色姓名
        :param level:角色等級
        :param blood:角色血量
        '''
        Rloe.__init__(self, name, level, blood)
        self.attack_power = attack_power
    def fight(self):   #角色攻擊行為
        print('魔法攻擊')
    def cure(self):  # 角色技能
        print('治療')

繼承搜尋

搜尋原則:(訪問類的屬性或方法)

  • 如果找不到轉到其父類中查詢
  • 如果再找不到轉到其父類的父類中查詢

例項:

class BaseClass:
    attritube = 1
    def method(self):
        pass
class DeriverClass:    #簡單繼承,沒有任何的封裝,重寫
    pass
print(DeriverClass.__dict__)  #DeriverClass中沒有attritube與method
print(BaseClass.__dict__)     #BaseClass中有

重用父類的 _ init_

左邊的self 是 劍士(子類)的例項 右邊的self是也是劍士的例項

這裡寫圖片描述

頂級基類 object

class ClassName:
    pass
class ClassN(object):
    pass
print(ClassName.__bases__)
print(ClassN.__bases__)

思考:為什麼返回的是一個元祖 ?

  • 有可能繼承多個類(及多繼承),以元組顯示。

階段二:多重繼承

多重繼承 問題引入

問題一: 一個類只能有一個基類嘛 ?

問題二: 如果有多個基類,如果有同名屬性和方法,應該如何選擇?

問題三: 有沒有一種更加優雅的方式呼叫父類的方法 ?

繼承關係圖:

這裡寫圖片描述

程式碼實現如下:

class D:
    pass
class E:
    pass
class C:
    pass
class B(D,E):
    pass
class A(B,C):
    pass

print(A.mro())

結果輸出:

[<class '__main__.A'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.E'>, <class '__main__.C'>, <class 'object'>]

程序已結束,退出程式碼0

MRO-C3 搜尋分析

S[D] = <D O>
S[E] = <E O>
S[C] = <C O>

S[B] = B + merge(S[D], S[E], <D E>)
        = B + merge(<D O>, <E O>, <D E>)
        = <B D> + merge(O, <E O>, E)
        = <B D E O>

S[A] = A + merge(S[B], S[C], <B C>)
        = A + merge(<B D E O>, <C O>, <B C>)
        = <A B> + merge(<D E O>, <C O>, C)
        = <A B D> + merge(<E O>, <C O>, C)
        = <A B D E> + merge(O, <C O>, C)
        = <A B D E C O>

由於衝突導致的不能繼承

這裡寫圖片描述

程式碼實現如下:

class A:
    pass
class B:
    pass
class C(A,B):
    pass
class D(B,A):
    pass
class E(C,D):
    pass

print(E.mro())

結果輸出:

Traceback (most recent call last):
  File "G:/xxx/xxx/xxx/xxx/TTT.py", line 14, in <module>
    class E(C,D):
TypeError: Cannot create a consistent method resolution
order (MRO) for bases A, B

MRO-C3 搜尋分析

S[A] = <A O>
S[B] = <B O>

S[C] = C + merge(S[A], S[B], <A B>)
        = C + merge(<A O>, <B O>, <A B>)
        = <C A> + merge(O, <B O>, <B>)
        = <C A B O>
S[D] = <D B A O>

S[E] = E + merge(S[C], S[D], <C D>)
        = E + merge(<C A B O>, <D B A O>, <CD>)
        = <E C> + merge(<A B O>, <D B A O>, <D>)
        = <E C D> + merge(<A B O>, <B A O>)    # 衝突

鴨子型別

例項:

def draw_fight(role):
  print('role',end='')
  role.fight()    #其實並不關心,role是不是一個例項
class SwordsMan:
    def __init__(self, name, level, blood, attack_power):
        '''
        :param name:角色姓名
        :param level:角色等級
        :param blood:角色血量
        '''
        self.name = name
        self.level = level
        self.blood = blood
        self.power = attack_power

    def fight(self):   #角色攻擊行為
        print('物理攻擊')
    def __str__(self):
        return "{clc}({name},{level},{blood})".format(clc = self.__class__.__name__,
                                                      name = self.name,
                                                      level = self.level,
                                                      blood = self.blood)
class Magician:
    def __init__(self, name, level, blood, magic_power):
        '''
        :param name:角色姓名
        :param level:角色等級
        :param blood:角色血量
        '''
        self.name = name
        self.level = level
        self.blood = blood
        self.power = magic_power
    def fight(self):   #角色攻擊行為
        print('魔法攻擊')
    def __str__(self):
        return "{clc}({name},{level},{blood})".format(clc = self.__class__.__name__,
                                                      name = self.name,
                                                      level = self.level,
                                                      blood = self.blood)

s = SwordsMan('lili',19,3000,150)
m = Magician('haha',18,1000,330)
draw_fight(s)  #打印出:role物理攻擊
draw_fight(m)  #打印出:role魔法攻擊

如果走起路來像鴨子,或者叫起來像鴨子,那就是鴨子!

基於多繼承的 Mix-in 設計模式

這裡寫圖片描述

原則:

  • 最好,多繼承就一層,且是最後一層
  • 注意:一般,“Mix-in類”是繼承的終點 !

階段三:super 內建函式

如何更加優雅的呼叫父類中方法?

程式碼實現如下:

劍士super方法改進:

class SwordsMan(Rloe):     #繼承自Role
    def __init__(self,name,level,blood,attack_power):
        '''
        :param name:角色姓名
        :param level:角色等級
        :param blood:角色血量
        '''
        super().__init__(name,level,blood)
        self.attack_power = attack_power
    def fight(self):   #角色攻擊行為
        print('物理攻擊')

法師劍士super方法改進:

class Magician:        #繼承自Role
    def __init__(self,name,level,blood,magic_power):
        '''
        :param name:角色姓名
        :param level:角色等級
        :param blood:角色血量
        '''
        super().__init__(name, level, blood)
        self.attack_power = attack_power
    def fight(self):   #角色攻擊行為
        print('魔法攻擊')
    def cure(self):  # 角色技能
        print('治療')

super不需要再傳self、super是通過mro查詢的

練習:

eg:

假設你正在參與潭州教育公司的軟體學員管理系統開發,需要你為系統設計學員類:潭州教育軟體類別:

  1. C/C++
  2. Web前端
  3. Python

請設計一個基類表示學員,然後使用繼承來實現各科目的軟體學員。

程式碼實現如下:

class Student:
    def __init__(self,name,age,sex):
        '''
        :param name:學員姓名
        :param age:學員年齡
        :param sex:學員性別
        '''
        self.name = name
        self.age =age
        self.sex = sex
    def __str__(self):
        return "{clc}({name},{age},{sex})".format(clc = self.__class__.__name__,
                                                      name = self.name,
                                                      age = self.age,
                                                      sex = self.sex)

    def learn(self):  # 學員學習課程
        raise NotImplementedError('必須在子類中實現該方法')

class C(Student):     #繼承自Student
    def __init__(self,name,age,sex,lesson):
        '''
         :param name:學員姓名
        :param age:學員年齡
        :param sex:學員性別
        '''
        super().__init__(name,age,sex)
        self.lesson = lesson
    def learn(self):   #學習課程
        print('學習C/C++課程')

class Web(Student):         #繼承自Student
    def __init__(self,name,age,sex,lesson):
        '''
         :param name:學員姓名
        :param age:學員年齡
        :param sex:學員性別
        '''
        super().__init__(name,age,sex)
        self.lesson = lesson
    def learn(self):   #學習課程
        print('學習Web前端課程')

class Python(Student):         #繼承自Student
    def __init__(self,name,age,sex,lesson):
        '''
         :param name:學員姓名
        :param age:學員年齡
        :param sex:學員性別
        '''
        super().__init__(name,age,sex)
        self.lesson = lesson
    def learn(self):   #學習課程
        print('學習Python課程')
c= C('lili',18,'M','c/c++')
w= Web('haha',19,'F','Web前端')   
p= Python('dada',20,'M','Python')
print(c)
c.learn()
print(w)
w.learn()
print(p)
p.learn()

輸出結果:

C(lili,18,M)
學習C/C++課程
Web(haha,19,F)
學習Web前端課程
Python(dada,20,M)
學習Python課程
>>> 

相關推薦

python面向物件---03-繼承繼承super

python面向物件—03-繼承、多繼承、super 階段一:繼承 情景模式:假設你正在參與一個魔幻類角色遊戲的開發,公司需要你為這個遊戲設計兩個角色的類: 劍士 具有如下屬性: 角色名 角色等級 生命值 攻擊力 具有如下行為: 物理攻擊 法師

python - 面向物件的三大特徵:封裝繼承

面向物件三大特性 1.封裝:根據職責將屬性和方法封裝到一個抽象的類中 2.繼承:實現程式碼的重用,相同的程式碼不需要重複的寫 -3.多型 單繼承: 子類擁有父類的所有方法和屬性(子類只需封裝自己特有的方法) 舉例: class Animal: #

python面向物件學習(四)繼承

目錄 1. 單繼承 1.1 繼承的概念、語法和特點 1.2 方法的重寫 1.3 父類的 私有屬性 和 私有方法 2. 多繼承 2.1 多繼承的使用注意事項 2.2 新式類與舊式(經典)類 1. 單繼承 1.1 繼承的概念、

python面向物件程式設計之組合與繼承

類與類之間有兩種關係:繼承和組合。多用組合少用繼承較好。 先來看兩個例子: 先定義兩個類,一個老師類,老師類有名字,年齡,出生的年,月和日,所教的課程等特徵以及走路,教書的技能。 class Teacher: def __init__(self,name,age,year,mon,day):

Python面向物件繼承

面向物件變成的基本思想:類和例項 類用於定義抽象型別---------------------人-----------------------------class  Person(object):------------------資料封裝class Person(object):  

python面向對象三大特性之繼承

nim 類的屬性 pri dog name 復用性 繼承 python2 調用方法 繼承 什麽是繼承     所謂繼承指提供了同一類對象共性的處理方法,子類繼承父類共性的東西。 這樣有利於代碼的復用性,即子類擁有父類的方法。通過繼承創建的新類稱為“子類”或“

【17】有關python面向對象編程的提高【繼承類屬性動態添加與限制添加屬性與方法@property】

爸爸 mce turn object get 寫法 pri import sel 一、多繼承 案例1:小孩繼承自爸爸,媽媽。在程序入口模塊再創建實例調用執行 #father模塊 class Father(object): def __init__(self,mon

面向物件的三大特性:封裝繼承

1.封裝  將一些資訊放入類內部(private),不允許外部程式直接訪問,如果需要使用這些資訊則需要通過該類提供的方法來實現對資料資訊的操作和訪問。 2.繼承(extends) 將已經存在的一個類A的屬性作為自己的屬性,並新增其他新的屬性或修改原來的方法使之符合新的需求所產生

Python基礎(三)--- Python面向物件oop,類方法和變數,繼承

一、面向物件oop ----------------------------------------------------- 1.類 用來描述具有相同的屬性和方法的物件的集合。 它定義了該集合中每個物件所共有的屬性和方法。 物件是類的例項。

Java面向物件筆記(封裝繼承抽象類介面)

面向物件的思想在現實生活中很常見,例如專案開發,老闆想要實現某個功能,但是他自己不會這些技術,所以他就會讓員工去做這些事情,通過藉助別的擁有你想要實現某些功能的過程就可以理解為面向物件。 面向物件有三大特性:封裝、繼承、多型。 1.封裝:即是把函式或者工具類的實

黑馬程式設計師——Java面向物件(二)之封裝繼承介面等

-----------android培訓、java培訓、java學習型技術部落格、期待與您交流!------------ 五、面向物件的特徵  面向物件主要有三大特徵: 1.特徵一 —— 封裝  1)定義:是指隱藏物件的屬性和實現細節,僅對外提供公共訪問方式。 2)好處:

以哲學的角度解釋面向物件的三大特徵(封裝繼承型)

<在此特向我的好哥們兒—小明哥,表示由衷的感謝,讓我對Java的理解更深入了一層。還是那句話,小明哥,等我去你那找你玩的時候請你吃大餐,哦,不對,是你請我吃大餐~啊,言歸正傳… 萬物皆物件 首先說一下類和物件的理解: 什麼是類,類就是一個類別,是一種抽象,是在概念這一

python 面向物件基礎梳理三 繼承派生與組合

什麼是繼承 繼承是一種建立新類的方式,是一種什麼是什麼的關係,繼承的功能之一就是解決程式碼重用的問題,繼承是一種建立新類的方式,在python 中,新建的一個類可以繼承一個或者多個父類,父類由可以成為基類或者超類,新建的類稱為派生類或子類。 繼承的分類 繼承可以分為 單繼承和多繼承,Python 2 和

java基礎之面向物件的三大特徵:封裝繼承型,學java必會!

java它是OOP語言(ObjectOrientedProgramming)面向物件程式語言,那麼什麼是物件?物件是什麼?毫無疑問這個問題有很多個答案,每個人對物件的理解是不一樣。 java面向物件的三大基本特徵之封裝: 我們為什麼要對我們的程式碼進行封裝?當我們定義一個人類的體重,要

面向物件:理解 Python 類的單繼承繼承

每種動物都有各自的特性,比如 老鼠會打洞 貓會爬樹 鯊魚會游泳 不同種類有不同的天性。而在程式設計師的思維中, 動物是物件, 天性是這個類方法或者屬性。 再延伸一下,比如Python是面向物件程式語言。有List、Str、Dict、Tuple等資料型別,這些

面向物件原則:高內聚低耦合。聚合繼承

面向物件的基本原則:多聚合,少繼承。低耦合,高內聚.【高內聚、低耦合】    內聚:每個模組儘可能獨立完成自己的功能,不依賴於模組外部的程式碼。    耦合:模組與模組之間介面的複雜程度,模組之間聯絡越複雜耦合度越高,牽一髮而動全身。    目的:使得模組的“可重用性”、“

Python面向物件程式設計(類和例項 訪問限制 繼承型 獲取物件資訊 例項屬性和類屬性)

面向物件程式設計——Object Oriented Programming,簡稱OOP,是一種程式設計思想。OOP把物件作為程式的基本單元,一個物件包含了資料和操作資料的函式。 資料封裝、繼承和多型是面向物件的三大特點 在Python中,所有資料型別都可以視

python學習筆記】Python面向物件的理解(封裝,繼承型)

說明 提到面向物件,總是離不開幾個重要的術語:多型(Polymorphism),繼承(Inheritance)和封裝(Encapsulation)。Python也是一種支援OOP的動態語言,本文將簡單闡述Python對面向物件的支援。 在討論Python的O

lua面向物件實現-類例項化物件繼承繼承lua單例模式

lua面向物件實現: 一個類就像是一個建立物件的模具。有些面嚮物件語言提供了類的概念,在這些語言中每個物件都是某個特定類的例項。lua則沒有類的概念,每個物件只能自定義行為和形態。不過,要在lua中模擬類也並不困難。 lua中,面向物件是用元表這個機制來實現。

PHP面向物件深入理解之二(封裝繼承克隆)

 1.封裝  所謂封裝就是隱藏內部實現細節,提供外部訪問方式  將一系列私有的特徵儲存起來 class Person { private $ID; public function setID($id) { $this