自學Python5.5-面向對象三大基本特徵_繼承

自學Python之路-Python基礎+模塊+面向對象
自學Python之路-Python網絡編程
自學Python之路-Python併發編程+數據庫+前端
自學Python之路-djangohtml

自學Python5.5-面向對象三大基本特徵_繼承

1、初始繼承(單繼承)前端

1.1  繼承概念

繼承是指這樣一種能力:它可使用現有類的全部功能,並在無需從新編寫原來的類的狀況下對這些功能進行擴展。python

  • 經過繼承建立的新類稱爲「子類」或「派生類」。
  • 被繼承的類稱爲「基類」、「父類」或「超類」。
  • 繼承的過程,就是從通常到特殊的過程。要實現繼承,能夠經過「繼承」(Inheritance)和「組合」(Composition)來實現。
  • 一個子類能夠被多個類繼承。
  • 一個子類能夠繼承多個父類(只有在python裏面纔有)。
class A(object):pass   # 父類,基類,超類
class B:pass   # 父類,基類,超類
class A_son(A,B):pass # 子類,派生類
class AB_son(A):pass # 子類,派生類

沒有繼承父類,默認繼承object 。數據庫

1.2  繼承與抽象(先抽象後繼承)

抽象即抽取相似或者說比較像的部分。
抽象最主要的做用是劃分類別(能夠隔離關注點,下降複雜度)。django

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

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

# 好比舉例人狗大戰。 如下有兩個類,你會發現兩個類有共同點
class Dog:
    def __init__(self,name,aggr,hp):
        self.name = name
        self.aggr = aggr
        self.hp = hp
    def bitc(self,person):
        person.hp -= self.aggr
class person:
    def __init__(self,name,aggr,hp,sex):
        self.name = name
        self.aggr = aggr
        self.hp = hp
        self.sex = sex
        self.money = 0
    def attack(self,dog):
        person.hp -= self.aggr
    def get_weapon(self,weapon):
        if self.money >= weapon.price:
             self.money -= weapon.price
             self.get_weapon = weapon
             self.aggr += weapon.aggr
        else:
            print("餘額不足,請先充值")  

 將以上兩個類相同的地方建立一個新的類, 兩個類在繼承新的類。併發

class Animal:
    def __init__(self,name,aggr,hp):
        self.name = name  #人和狗都有本身的暱稱
        self.aggr = aggr  #人和狗都有本身的攻擊力
        self.hp = hp      #人和狗都有本身的生命值
class Dog(Animal):
    def bitc(self,person):
        person.hp -= self.aggr
class person(Animal):
    pass
Liu = Dog("劉老闆",200,500)
print(Liu.name)

舉個例子:python2.7

一個狗類: 吃、喝、看門編程語言

一個鳥類: 吃、喝、下單

class Animal:
    def __init__(self):
        print('執行Animal.__init__')
        self.func()
    def eat(self):
        print('%s eating'%self.name)
    def drink(self):
        print('%s drinking'%self.name)
    def func(self):
        print('Animal.func')
class Dog(Animal):
    def guard(self):
         print('guarding')
    def func(self):
         print('Dog.func')
class Bird(Animal):
    def __init__(self,name):
        self.name = name
    def lay(self):
        print('laying')  

好比定義一個實例 dog = Dog(),其中產生了一個問題

當執行Dog類的時候,Dog類沒有__init__(self)就執行父類Animal的__init__(self),而後執行了self.func(),此時Animal和Dog類同時擁有self.func(),那麼它執行哪一個類的self.func()? 答案是:Dog的self.func()

提示:

用已經有的類創建一個新的類,這樣就重用了已經有的軟件中的一部分設置大部分,大大生了編程工做量,這就是常說的軟件重用,不只能夠重用本身的類,也能夠繼承別人的,好比標準庫,來定製新的數據類型,這樣就是大大縮短了軟件開發週期,對大型軟件開發來講,意義重大。

1.3  派生

固然子類也能夠添加本身新的屬性或者在本身這裏從新定義這些屬性(不會影響到父類),須要注意的是,一旦從新定義了本身的屬性且與父類重名,那麼調用新增的屬性時,就以本身爲準了。

# 好比接上面的舉例。
class Animal:
    def __init__(self,name,aggr,hp):
        self.name = name
        self.aggr = aggr
        self.hp = hp
class Dog(Animal):
    def __init__(self,name,aggr,hp,kind):
        self.kind = kind
    def bitc(self,person):
        person.hp -= self.aggr
Liu = Dog("劉老闆",20,500,"吉娃娃")
print(Liu.name)     # 報錯,由於只執行Dog類裏面的_init_,可是裏面沒有name 

class Animal:
    def __init__(self,name,aggr,hp):
        self.name = name
        self.aggr = aggr
        self.hp = hp
    def eat(self):
        print('吃藥回血')
        self.hp+=100
class Dog(Animal):
    def __init__(self,name,aggr,hp,kind):
        Animal.__init__(self,name,aggr,hp)  #
        self.kind = kind       # 派生屬性(父類沒有的,子類新增的屬性)
class Person(Animal):
    def __init__(self,name,aggr,hp,sex):
        Animal.__init__(self,name,aggr,hp)
        self.sex = sex       # 派生屬性
        self.money = 0       # 派生屬性
Liu = Dog('劉老闆',20,500,'吉娃娃')
Liu.eat()       #使用的繼承父類animal的eat方法
print(Liu.hp)
tong = Person('tong',1,2,None)
tong.eat()      #使用的繼承父類animal的eat方法
print(tong.hp)

class Animal:
    def __init__(self,name,aggr,hp):
        self.name = name
        self.aggr = aggr
        self.hp = hp
    def eat(self):
        print('吃藥回血')
        self.hp+=100
class Dog(Animal):
    def __init__(self,name,aggr,hp,kind):
        Animal.__init__(self,name,aggr,hp)  #
        self.kind = kind       # 派生屬性(父類沒有的,子類有的屬性)
    def bite(self,person):     # 派生方法(父類沒有的,子類有的方法)
        person.hp -= self.aggr
class Person(Animal):
    def __init__(self,name,aggr,hp,sex):
        Animal.__init__(self,name,aggr,hp)
        self.sex = sex       # 派生屬性
        self.money = 0       # 派生屬性
    def attack(self,dog):
        dog.hp -= self.aggr
    def get_weapon(self,weapon):
        if self.money >= weapon.price:
            self.money -= weapon.price
            self.weapon = weapon
            self.aggr += weapon.aggr
        else:
            print("餘額不足,請先充值")
Liu = Dog('劉老闆',20,500,'吉娃娃')
Liu.eat()       #使用的繼承父類animal的eat方法
print(Liu.hp)

tong = Person('tong',1,2,None)
tong.eat()      #使用的繼承父類animal的eat方法
print(tong.hp)

Liu.bite(tong) #使用Dog類本身的派生方法
print(tong.hp)

在子類中,新建的重名的函數屬性,在編輯函數內功能的時候,有可能須要重用父類中重名的那個函數功能,應該是用調用普通函數的方式,即:類名.func(),此時就與調用普通函數無異了,所以即使是self參數也要爲其傳值.

在python3中,子類執行父類的方法也能夠直接用super方法。

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

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

a = A()
b = B()
b.hahaha()
super(B,b).hahaha()

 總結:

  • 父類中沒有的屬性 在子類中出現 叫作派生屬性
  • 父類中沒有的方法 在子類中出現 叫作派生方法
  • 只要是子類的對象調用,子類中有的名字 必定用子類的,子類中沒有才找父類的,若是父類也沒有報錯
  • 若是父類、子類都有,使用子類的
  •      若是還想用父類的,單獨調用父類的
  •      父類名.方法名,須要本身傳self參數
  •      super().方法名,不須要本身傳只在新式類中有,python3中全部類都是新式類
  • 正常的代碼中,單繼承 === 減小了代碼的重複
  • 繼承表達的是一種 子類是父類的關係
class Animal:
    def __init__(self,name,aggr,hp):
        self.name = name
        self.aggr = aggr
        self.hp = hp
    def eat(self):
        print('吃藥回血')
        self.hp+=100
class Dog(Animal):
    def __init__(self,name,aggr,hp,kind):
        super().__init__(name,aggr,hp)    #等價於Animal.__init__(self,name,aggr,hp),不須要傳self
        self.kind = kind       # 派生屬性(父類沒有的,子類新增的屬性)
Liu = Dog('劉老闆',20,500,'吉娃娃')
Liu.eat()          #使用的繼承父類animal的eat方法
print(Liu.hp)

super()能夠在類內使用,也能夠在類外使用。

  • super()在類內使用:不須要傳默認參數,就是類名和self
  • super()在類外使用:必須傳類名和對象名
#super()在類外和類內
class Animal:
    def __init__(self,name,aggr,hp):
        self.name = name
        self.aggr = aggr
        self.hp = hp
    def eat(self):
        print('吃藥回血')
        self.hp+=100
class Dog(Animal):
    def __init__(self,name,aggr,hp,kind):
        super().__init__(name,aggr,hp)    #等價於Animal.__init__(self,name,aggr,hp)
        self.kind = kind       # 派生屬性(父類沒有的,子類新增的屬性)
    def eat(self):print("dog eating")
Liu = Dog('劉老闆',20,500,'吉娃娃')
print(Liu.name)
Liu.eat()             # 執行的是Dog類裏面的def eat(self):print("dog eating")
super(Dog,Liu).eat()  # 執行的是父類裏面的def eat(self):

2、多繼承

class A:
    def func(self):print("A")
class B:
    def func(self):print("B")
class C:
    def func(self):print("C")
class D(A,B,C):  # D類繼承A,B,C,多繼承
    def func(self):print("D")

d = D()
d.func()   #此時調用的D類的func()

class A:
    def func(self):print("A")
class B:
    def func(self):print("B")
class C:
    def func(self):print("C")
class D(A,B,C):  # D類繼承A,B,C,多繼承
    pass
    #def func(self):print("D")

d = D()
d.func()   #此時調用的A類的func(),由於class D(A,B,C),A類離D最近

2.1 多繼承---經典案例----菱形繼承(鑽石繼承)

B、C繼承A,D繼承B、C

class A:
    def func(self):print("A")
class B(A):   # B類繼承A
    def func(self):print("B")
class C(A):   # C類繼承A
    def func(self):print("C")
class D(B,C):  # D類繼承B,C
    pass
    #def func(self):print("D")

d = D()
d.func()  

class A:
    def func(self):print("A")
class B(A):   # B類繼承A
    pass
    #def func(self):print("B")
class C(A):   # C類繼承A
    def func(self):print("C")
class D(B,C):  # D類繼承B,C
    pass
    #def func(self):print("D")

d = D()
d.func()

class A:
    def func(self):print("A")
class B(A):   # B類繼承A
    pass
    #def func(self):print("B")
class C(A):   # C類繼承A
    pass
    #def func(self):print("C")
class D(B,C):  # D類繼承B,C
    pass
    #def func(self):print("D")

d = D()
d.func()

同理如下兩個問題,繼承順序以下圖:

 

 

2.2  總結

多繼承中,咱們子類的對象調用一個方法,默認是就近原則,找的順序是什麼?

  • 經典類中 深度優先
  • 新式類中 廣度優先

① python2.7 新式類和經典類共存,新式類要繼承object

② python3 只有新式類,默認繼承object

③ 經典類和新式類還有一個區別:mro方法只在新式類中存在,類名.mro方法,查看廣度優先的繼承順序。

④ super 只在python3中存在

⑤ super的本質 :不是單純找父類 而是根據調用者的節點位置的廣度優先順序來的

class A(object):
    def func(self): print('A')

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

class C(A):
    def func(self):
        super().func()
        print('C')

class D(B,C):
    def func(self):
        super().func()
        print('D')

b = D()
b.func()  

......

相關文章
相關標籤/搜索