亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Python面向?qū)ο缶幊獭^承與派生

系統(tǒng) 1864 0

Python面向?qū)ο缶幊獭^承與派生

一、初始繼承

1、什么是繼承

繼承指的是類與類之間的關(guān)系,是一種 什么“是”什么 的關(guān)系,繼承的功能之一就是用來解決代碼重用問題。

繼承是一種創(chuàng)建新類的方式,在python中,新建的類可以繼承一個或多個父類,父類又可以成為基類或超類,新建的類稱為派生類或子類

2、python中類的繼承分為:單繼承和多繼承

          
            class ParentClass1: #定義父類
    pass

class ParentClass2: #定義父類
    pass

class SubClass1(ParentClass1): #單繼承,基類是ParentClass1,派生類是SubClass
    pass

class SubClass2(ParentClass1,ParentClass2): #python支持多繼承,用逗號分隔開多個繼承的類
    pass
          
        

3、查看繼承

          
            >>> SubClass1.__bases__ #__base__只查看從左到右繼承的第一個子類,__bases__則是查看所有繼承的父類
(
            
              ,)
>>> SubClass2.__bases__
(
              
                , 
                
                  )
                
              
            
          
        

4、經(jīng)典類與新式類

          
            1.只有在python2中才分新式類和經(jīng)典類,python3中統(tǒng)一都是新式類
2.在python2中,沒有顯式的繼承object類的類,以及該類的子類,都是經(jīng)典類
3.在python2中,顯式地聲明繼承object的類,以及該類的子類,都是新式類
4.在python3中,無論是否繼承object,都默認(rèn)繼承object,即python3中所有類均為新式類
          
        

注:如果沒有指定基類,python的類會默認(rèn)繼承object類,object是所有python類的基類,它提供了一些常見方法(如 __str__ )的實現(xiàn)。

          
            >>> ParentClass1.__bases__
(
            
              ,)
>>> ParentClass2.__bases__
(
              
                ,)
              
            
          
        

二、繼承與抽象(先抽象再繼承)

抽象即抽取類似或者說比較像的部分。

抽象分成兩個層次:

1、將奧巴馬和梅西這倆對象比較像的部分抽取成類;

2、將人,豬,狗這三個類比較像的部分抽取成父類。

抽象最主要的作用是劃分類別(可以隔離關(guān)注點,降低復(fù)雜度)

Python面向?qū)ο缶幊獭^承與派生_第1張圖片

繼承:是基于抽象的結(jié)果,通過編程語言去實現(xiàn)它,肯定是先經(jīng)歷抽象這個過程,才能通過繼承的方式去表達(dá)出抽象的結(jié)構(gòu)。

抽象只是分析和設(shè)計的過程中,一個動作或者說一種技巧,通過抽象可以得到類。

Python面向?qū)ο缶幊獭^承與派生_第2張圖片

三、繼承與重用性

在開發(fā)程序的過程中,如果我們定義了一個類A,然后又想新建立另外一個類B,但是類B的大部分內(nèi)容與類A的相同時,我們不可能從頭開始寫一個類B,這就用到了類的繼承的概念。

通過繼承的方式新建類B,讓B繼承A,B會‘遺傳’A的所有屬性(數(shù)據(jù)屬性和函數(shù)屬性),實現(xiàn)代碼重用。

          
            class Hero:
    def __init__(self,nickname,aggressivity,life_value):
        self.nickname=nickname
        self.aggressivity=aggressivity
        self.life_value=life_value

    def move_forward(self):
        print('%s move forward' %self.nickname)

    def move_backward(self):
        print('%s move backward' %self.nickname)

    def move_left(self):
        print('%s move forward' %self.nickname)

    def move_right(self):
        print('%s move forward' %self.nickname)

    def attack(self,enemy):
        enemy.life_value-=self.aggressivity
class Garen(Hero):
    pass

class Riven(Hero):
    pass

g1=Garen('草叢倫',100,300)
r1=Riven('銳雯雯',57,200)

print(g1.life_value) #結(jié)果:300
r1.attack(g1)
print(g1.life_value) #結(jié)果:243
          
        

注:用已經(jīng)有的類建立一個新的類,這樣就重用了已經(jīng)有的軟件中的一部分設(shè)置大部分,大大節(jié)省了編程工作量,這就是常說的軟件重用,不僅可以重用自己的類,也可以繼承別人的,比如標(biāo)準(zhǔn)庫,來定制新的數(shù)據(jù)類型,這樣就是大大縮短了軟件開發(fā)周期,對大型軟件開發(fā)來說,意義重大。

四、再看屬性查找

像g1.life_value之類的屬性引用,會先從實例中找life_value然后去類中找,然后再去父類中找...直到最頂級的父類。那么如何解釋下面的打印結(jié)果呢?

          
            class Foo:
    def f1(self):
        print('Foo.f1')

    def f2(self):
        print('Foo.f2')
        self.f1()

class Bar(Foo):
    def f1(self):
        print('Bar.f1')


b=Bar()
b.f2()

# 打印結(jié)果:
# Foo.f2
# Bar.f1
          
        

五、派生

當(dāng)然子類也可以添加自己新的屬性或者在自己這里重新定義這些屬性(不會影響到父類),需要注意的是,一旦重新定義了自己的屬性且與父類重名,那么調(diào)用新增的屬性時,就以自己為準(zhǔn)了。

          
            class Riven(Hero):
    camp='Noxus'
    def attack(self,enemy): #在自己這里定義新的attack,不再使用父類的attack,且不會影響父類
        print('from riven')
    def fly(self): #在自己這里定義新的
        print('%s is flying' %self.nickname)
          
        

在子類中,新建的重名的函數(shù)屬性,在編輯函數(shù)內(nèi)功能的時候,有可能需要重用父類中重名的那個函數(shù)功能,應(yīng)該是用調(diào)用普通函數(shù)的方式,即:類名.func(),此時就與調(diào)用普通函數(shù)無異了,因此即便是self參數(shù)也要為其傳值。

          
            class Riven(Hero):
    camp='Noxus'
    def __init__(self,nickname,aggressivity,life_value,skin):
        Hero.__init__(self,nickname,aggressivity,life_value) #調(diào)用父類功能
        self.skin=skin #新屬性
    def attack(self,enemy): #在自己這里定義新的attack,不再使用父類的attack,且不會影響父類
        Hero.attack(self,enemy) #調(diào)用功能
        print('from riven')
    def fly(self): #在自己這里定義新的
        print('%s is flying' %self.nickname)

r1=Riven('銳雯雯',57,200,'比基尼')
r1.fly()
print(r1.skin)

'''
運(yùn)行結(jié)果
銳雯雯 is flying
比基尼
'''
          
        

六、繼承的實現(xiàn)與原理

python到底是如何實現(xiàn)繼承的,對于你定義的每一個類,python會計算出一個方法解析順序(MRO)列表,這個MRO列表就是一個簡單的所有基類的線性順序列表,例如

          
            >>> F.mro() #等同于F.__mro__
[
            
              , 
              
                , 
                
                  , 

                  
                    , 
                    
                      , 
                      
                        , 
                        
                          ]
                        
                      
                    
                  
                
              
            
          
        

為了實現(xiàn)繼承,python會在MRO列表上從左到右開始查找基類,直到找到第一個匹配這個屬性的類為止。而這個MRO列表的構(gòu)造是通過一個C3線性化算法來實現(xiàn)的。我們不去深究這個算法的數(shù)學(xué)原理,它實際上就是合并所有父類的MRO列表并遵循如下三條準(zhǔn)則:

1、子類會先于父類被檢查。

2、多個父類會根據(jù)它們在列表中的順序被檢查。

3、如果對下一個類存在兩個合法的選擇,選擇第一個父類。

在Java和C#中子類只能繼承一個父類,而Python中子類可以同時繼承多個父類,如果繼承了多個父類,那么屬性的查找方式有兩種,分別是:深度優(yōu)先和廣度優(yōu)先。

Python面向?qū)ο缶幊獭^承與派生_第3張圖片

Python面向?qū)ο缶幊獭^承與派生_第4張圖片

示范代碼:

          
            class A(object):
    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):
    # def test(self):
    #     print('from F')
    pass
f1=F()
f1.test()
print(F.__mro__) #只有新式才有這個屬性可以查看線性列表,經(jīng)典類沒有這個屬性

#新式類繼承順序:F->D->B->E->C->A
#經(jīng)典類繼承順序:F->D->B->A->E->C
#python3中統(tǒng)一都是新式類
#pyhon2中才分新式類與經(jīng)典類
          
        

七、在子類中調(diào)用父類的方法

在子類派生出的新方法中,往往需要重用父類的方法,我們有兩種方式實現(xiàn)

方式一:指名道姓,即父類名.父類方法()

          
            class Vehicle: #定義交通工具類
     Country='China'
     def __init__(self,name,speed,load,power):
         self.name=name
         self.speed=speed
         self.load=load
         self.power=power

     def run(self):
         print('開動啦...')

class Subway(Vehicle): #地鐵
    def __init__(self,name,speed,load,power,line):
        Vehicle.__init__(self,name,speed,load,power)
        self.line=line

    def run(self):
        print('地鐵%s號線歡迎您' %self.line)
        Vehicle.run(self)  # 指名道姓的調(diào)用

line13=Subway('中國地鐵','180m/s','1000人/箱','電',13)
line13.run()
          
        

方式二:super()

          
            class Vehicle: #定義交通工具類
     Country='China'
     def __init__(self,name,speed,load,power):
         self.name=name
         self.speed=speed
         self.load=load
         self.power=power

     def run(self):
         print('開動啦...')

class Subway(Vehicle): #地鐵
    def __init__(self,name,speed,load,power,line):
        #super(Subway,self) 就相當(dāng)于實例本身 在python3中super()等同于super(Subway,self)
        super().__init__(name,speed,load,power)
        self.line=line

    def run(self):
        print('地鐵%s號線歡迎您' %self.line)
        super(Subway,self).run()

class Mobike(Vehicle):#摩拜單車
    pass

line13=Subway('中國地鐵','180m/s','1000人/箱','電',13)
line13.run()
          
        

這兩種方式的區(qū)別是:方式一是跟繼承沒有關(guān)系的,而方式二的super()是依賴于繼承的, 并且即使沒有直接繼承關(guān)系,super仍然會按照mro繼續(xù)往后查找。

          
            #A沒有繼承B,但是A內(nèi)super會基于C.mro()繼續(xù)往后找
class A:
    def test(self):
        super().test()
class B:
    def test(self):
        print('from B')
class C(A,B):
    pass

c=C()
c.test() #打印結(jié)果:from B


print(C.mro())
#[
            
              , 
              
                , 
                
                  , 
                  
                    ]
                  
                
              
            
          
        

更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 成人手机看片 | 日韩爱爱视频 | 色综合天天综合中文网 | 伦理一区二区 | 夜夜爽日日澡人人添 | 国产精品免费在线播放 | 福利免费在线 | 农村高清性色生活片 | 国产麻豆久久 | 日韩三级不卡 | 色婷婷六月桃花综合影院 | 色一色综合 | 久久996re热这里有精品 | 亚洲欧美一级久久精品 | 日韩 亚洲 欧美 中文 高清 | 国产高清一级毛片在线不卡 | 在线私人影院 | 久久草在线看 | 欧美一区二区高清 | 欧美亚洲综合在线观看 | 亚洲国产国产综合一区首页 | 婷婷夜夜躁天天躁人人躁 | 国产在线观看一区二区三区 | 伊人日本| 精品国产免费人成高清 | 热久久久久久 | 91热成人精品国产免费 | 欧美一级网址 | 日韩你懂的 | 精品免费久久久久久成人影院 | 国产专区精品 | 色姑娘综合网 | 久久久久久一级毛片免费无遮挡 | 天天射天天干天天舔 | 亚洲视频免费在线播放 | 国产成人精品一区二三区 | 午夜影院免费在线观看 | 天天射网站| 成人精品国产亚洲 | 成年女人a毛片免费视频 | 国产精品99一区二区三区 |