[ python ] 繼承

什麼是繼承:java

繼承是一種建立新類的方式,在python中,新建一個類能夠繼承一個或多個父類,父類又可稱爲基類和超類,新建的類稱爲派生類或子類python

 

python 中繼承分爲:單繼承和多繼承算法

單繼承

class Father1:  # 定義父類
    print('class Father1')


class Father2:  # 定義父類
    print('class Father2')


class Son1(Father1):  # 單繼承,父類:Father1 子類:Son1
    pass


class Son2(Father1, Father2):  # 多繼承: 父類:Father1, Father2 子類:Son2
    pass

 

 

使用 __bases__ 查看繼承:編程

__bases__: 查看子類全部的父類。編程語言

print(Son1.__bases__)
print(Son2.__bases__)

執行結果:
(<class '__main__.Father1'>,)
(<class '__main__.Father1'>, <class '__main__.Father2'>)

 

 

繼承和抽象(先抽象再繼承)

抽象:抽取相似或者說比較像的部分。
抽象分爲兩個層次:
1. 講具體的對象進行分類,例如:將奧巴馬和梅西這倆對象比較像的部分抽取成類;
2. 又能夠將人、豬、狗這三類比較像的部分抽取爲父類(都是動物).ide

 

抽象最主要的做用是劃分類別:函數

 

繼承:是基於抽象的結果,經過編程語言去實現它,確定是先經歷抽象這個過程,才能經過繼承的方式去表達出抽象的結構;

抽象只是分析和設計的過程當中,一個動做或者說一種技巧,經過抽象能夠獲得類spa

 

 

繼承與重用性設計

有以下兩個類:人類和鳥類3d

class Person:
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex
        
        
class Bird:
    def __init__(self, name, age, kind):
        self.name = name
        self.age = age
        self.kind = kind

 

 

這兩個類中的屬性,有明顯的重複使用,在這種狀況下,就能夠爲這兩個類定義一個父類,以下:

class Animal:    # 抽取出來共同的屬性組成父類
    def __init__(self, name, age):
        self.name = name
        self.age = age

class Person(Animal):    # 子類繼承父類
    def __init__(self, name, age, sex):
        Animal.__init__(self, name, age)    # 須要注意調用父類的方式:父類名.方法名調用
        self.sex = sex    # 子類的派生屬性


class Bird(Animal):
    def __init__(self, name, age, kind):
        Animal.__init__(self, name, age)
        self.kind = kind    # 子類的派生屬性


p = Person('hkey', 20, 'male')
b = Bird('maque', 1, 'maque')
print(p.name)
print(b.name)

執行結果:
hkey
maque

 

 

用已經有的類創建一個新的類,這樣就重用了多數類中重複的屬性和方法,不只能夠重用本身的類,也能夠繼承別人的,這樣就大大縮短了軟件開發週期。

 

派生類

父類中沒有的屬性 在子類中出現 叫派生屬性
父類中沒有的方法 在子類中出現 叫派生方法

在繼承父類的同時,子類也能夠添加本身獨有的屬性和方法,可是若是定義了和父類重複的屬性和方法,那麼調用的時候,就會首先調用子類中的屬性和方法。

 

super函數

python3 中 super函數的使用

子類執行父類的方法也能夠直接使用super方法,以下例子幫助理解 super 的使用:

class A:
    def haha(self):
        print('A')

class B(A):
    def haha(self):
        super(B, self).haha()
        print('B')

a = A()
b = B()
b.haha()
print('------')
super(B, b).haha()

執行結果:
A
B
------
A

 

 

對於super函數,咱們能夠總結以下:

super函數只存在於python3中
super().方法名:是尋找父類的方法名並執行;
在類中方法裏能夠使用super函數,在外層也能夠直接使用super函數尋找父類的方法

class A:
    def test(self):    # 父類的方法
        print('A')

class B(A):
    def test(self):    # 子類的方法與父類的方法重複,當調用該方法時,首先調用子類的方法
        print('B')

b = B()
b.test()

執行結果:
B
class Animal:
    '''
    人和狗都是動物,因此創造一個Animal父類
    '''
    def __init__(self, name, aggr, hp):
        self.name = name
        self.aggr = aggr
        self.hp = hp

    def eat(self):
        print('%s is eating.' % self.name)


class Dog(Animal):
    '''
    狗類繼承 Animal 類
    '''
    def __init__(self, name, aggr, hp, tooth):
        super(Dog, self).__init__(name, aggr, hp)   # 使用 super 調用父類的方法
        self.tooth = tooth  # 派生屬性
    def bite(self, person):
        '''派生方法:狗有咬人的技能'''
        person.hp -= self.aggr


class Person(Animal):
    '''
    人類,繼承 Animal 類
    '''
    def __init__(self, name, aggr, hp, money):
        super(Person, self).__init__(name, aggr, hp)    # 使用 super 調用父類的方法
        self.money = money  # 派生屬性
    def attack(self, dog):
        '''派生方法:人有攻擊的技能'''
        dog.hp -= self.aggr

p = Person('kk', 5, 100, 0)
d = Dog('tt', 10, 50, 1000)

print(p.hp)
d.bite(p)
print(p.hp)

# 執行結果:
# 100
# 90
子類派生方法的使用

 

 

1. 經過繼承創建了派生類與基類之間的關係,它是一種‘是’的關係,好比白馬是馬,人是動物。
2. 當多個類有相同的功能,提取這些相同的功能作成基類(父類),用繼承比較好,好比教授是老師。

class Teacher:
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender
    def teach(self):
        print('teaching.')

class Professor(Teacher):
    pass

p1 = Professor('kk', 'male')
p1.teach()

 

 

多繼承

多繼承就是一個子類繼承多個父類的方式,這種方式並很少用。

class A:
    print('A')

class B:
    print('B')

class C(A, B):    # 子類繼承兩個基類的方式,執行也是從左到右
    pass


C()

執行結果:
A
B
C

 

 

繼承順序:
1. python的類能夠繼承多個類,java 和 C# 中則只能繼承一個類
2. python的類若是繼承了多個類,那麼尋找父類的方式有兩種:深度優先、廣度優先。

    當類是經典類, 多繼承的狀況下,會按照深度優先方式查找
    當類是新式類, 多繼承的狀況下,會按照廣度優先方式查找

    在python3中全都是新式類

class A:
    def test(self):
        print('from A')

class B(A):
    def test(self):
        print('from B')

class C(A):
    def test(self):
        print('from C')

class D(B):
    def test(self):
        print('from D')

class E(C):
    def test(self):
        print('from E')

class F(D, E):
    pass

f1 = F()
f1.test()
print(F.mro())

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

上面這段代碼以下圖:

 

 

新式類繼承順序:F -> D -> B -> E -> C -> A
經典類繼承順序: F -> D -> B -> A -> E -> C

 

 

繼承原理

對於你定義的每個類,python會計算出一個方法解析順序(MRO)列表,這個MRO列表就是一個簡單的全部基類的線性順序列表。

 

爲了實現繼承,python會在MRO列表上從左到右開始查找基類,直到找到第一個匹配這個屬性的類爲止。而這個MRO列表的構造是經過一個C3線性化算法來實現的。咱們不去深究這個算法的數學原理,
它實際上就是合併全部父類的MRO列表並遵循以下三條準則:

1.子類會先於父類被檢查
2.多個父類會根據它們在列表中的順序被檢查
3.若是對下一個類存在兩個合法的選擇,選擇第一個父類

 

繼承小結

繼承的做用:
1. 減小代碼的重用
2. 提升代碼可讀性
3. 規範編程模式

 

幾個名詞:抽象:抽象即抽取相似或說比較像的部分。是一個從具體到抽象的過程。繼承:子類繼承父類的方法和屬性派生:子類在父類方法和屬性的基礎上產生了新的方法和屬性

相關文章
相關標籤/搜索