1. 程式人生 > >Python()- 面向對象三大特性----繼承

Python()- 面向對象三大特性----繼承

obj kit 當前 酷狗 子類 jin 但是 init 情況下


繼承:

繼承是一種創建新類的方式,
在python中,新建的類可以繼承一個或多個父類(基類或超類),新建的類是所繼承的類的(派生類或子類)


人類和狗 有相同的屬性, 提取了一個__init__方法,在這個方法裏放一些共有的屬性
人類和狗 在相同的方法,提取了一個def func():方法,在這個方法裏放一些共有的方法

單繼承和多繼承

class Par1:
    pass
class Par2:
    pass
class Sub1(Par1):
    pass
class Sub2(Par1,Par2):
    pass
#__base__只查看從左到右的第一個父類,而__bases__查看所有父類
print(Sub1.__bases__)
#(<class ‘__main__.Par1‘>,)
print(Sub2.__bases__)
#(<class ‘__main__.Par1‘>, <class ‘__main__.Par2‘>)
------------------------------------
print(Par1.__base__)
#<class ‘object‘>

  

如果沒有指定基類,python的類默認繼承object類,object類是所有類的基類,它提供了一些常見的方法(如__str__)的實現

 

class Par1:
    def __init__(self,name):
        self.name = name
    def __str__(self):
        return self.name
p = Par1(‘kitty‘)
print(p)
# kitty

  

class Foo1:
def __init__(self,name):     # self是f對象
self.name = name
def __str__(self):
return self.name
class Foo2(Foo1):
a = 1
f = Foo2(‘kitty‘)     #Foo2中沒有__init__函數,就去基類去找,然後傳入參數
print(f.name)     # kitty

  

繼承與抽象:

世間本來沒有人類,只是很多個具體的人對象,後來把所有的人抽象成(劃規成)一類,才有了人類的概念
so: 抽象是從下往上
  繼承從上往下


繼承與重用性:

繼承的目的是為了減少代碼的重復性


比如:

  想創建一個b類, 但是發現b類的屬性大部分和a類的相同, 就讓b去繼承a的屬性,節省代碼

提示:用已經有的類建立一個新的類,這樣就重用了已經有的軟件中的一部分設置大部分,大大生了編程工作量,這就是常說的軟件重用,不僅可以重用自己的類,也可以繼承別人的,比如標準庫,來定制新的數據類型,這樣就是大大縮短了軟件開發周期,對大型軟件開發來說,意義重大.

經典類 和 新式類:

python3都是新式類 (新式類默認繼承object class Foo(object): == class Foo: )

python2中經典類和新式類共存

  • class Foo: 是經典類
  • class Foo(object): 是新式類

鉆石繼承:

  • 經典類: 深度優先,就是單線走到頭,再去其它線
  • 新式類: 就是單線走到剩余最後一個父類停止,再去找其它線,最後一條線走到尾

經典類繼承順序:

深度優先

技術分享圖片技術分享圖片

新式類繼承順序:

  廣度優先:

技術分享圖片

如果找到b就去找c c再去找e e在去找f f沒有就報錯了 因為f找不到d 單線
=====================================================
python2 中: 最原始的加上object,往後的都會繼承object
======================================

再來看:

class D:
def __init__(self):
print(d)
class C(D):
def __init__(self):
print(c)
super().__init__()
class B(D):
def __init__(self):
print(b)
super().__init__()
class A(B,C):
def __init__(self):
print(a)
super().__init__()
#mro
a = A()
print(A.mro())
##結果如下:
a
b
c
d
[<class __main__.A>, <class __main__.B>, <class __main__.C>, <class __main__.D>, <class object>]
和mro的順序一樣 廣度優先 (super只有新式類中有)
在多繼承中,super不只是尋找當前類的父類,而是依據mro順序,
從A節點出發,根據廣度優先排序查找下一個類

 

派生


派生:

class A: # 基類(提取了狗和人的共同屬性)
def __init__(self,name, aggressivity, life_value): #裏面的self是對象
self.name = name
self.aggressivity = aggressivity
self.life_value = life_value
def eat(self):
print(‘A eating‘)
class Dog(A): # 定義一個狗類
def __init__(self,name, aggressivity, life_value,breed,):     #派生一個__init__方法
#A.__init__(self,name, aggressivity, life_value) : 類名.__init__(參數) 
super().__init__(name, aggressivity, life_value)     #調用基類__init__方法:super().__init__()
self.breed = breed       # 每一只狗都有自己的品種;
def bite(self,people):     #派生bite方法 父類中沒有的屬性&方法
people.life_value -= self.aggressivity
def eat(self):   #重新定義eat (派生)
A.eat(self)   #如果想加上父類的方法: A.eat(對象)
print(‘dog eating‘) 
class Person(A):   # 定義一個人類
def __init__(self,name, aggressivity, life_value,money):   #派生
super().__init__(name, aggressivity, life_value)     #調用基類__init__方法
self.money = money
def attack(self,dog):
dog.life_value -= self.aggressivity
def get_weapon(self,weapon_obj):
if self.money > weapon_obj.price:
self.money -= weapon_obj.price         # 金老板花錢買武器
self.weapon = weapon_obj             # 金老板裝備打狗棒
self.aggressivity += weapon_obj.aggr     # 金老板的攻擊力增加了
jin = Person(‘jin‘,250,250,100)
dog = Dog(‘酷狗‘,33,50,‘藏獒‘)
print(jin.name)                     # jin
print(jin.money)               # 100
print(dog.name)                 # 酷狗
print(dog.breed)             # 藏獒
dog.eat()
# A eating
# dog eating
-------------------
A.eat(dog)     #A eating  類名.方法名(對象名)
--------------------------------
super(Dog,dog).eat()   #A eating super(類名,對象名) super在外面用,必須傳參數
========================================    

  

派生方法和屬性:
1.在子類中增加父類沒有的
2.如果再調用父類的的方法和屬性

   父類.__init__(self,參數...)

   super()__init__(參數...) ? 指名道姓調用

  在類外面用super的時候, super(子類名,對象).屬性
  

小結:

子類有,用自己的,沒有用父類的
子類有,父類有,仍然想用父類的:
經典類: 父類.__init__(self,參數...) 父類.方法名(對象)
新式類: super().__init__(參數...) 父類.方法名(對象)

一般情況下super都滿足了
指名道姓調用父類的方法 父類.方法(self) self是子類的對象


例題:打印結果

class Foo:
def __init__(self): (self是對象,對象自己有func())
self.func()
def func(self):
print(父類)
class Son(Foo):
def func(self):
print(子類)
s = Son()
#子類
----------------
print(Son.mro()) 新式類才有的查看繼承順序的方法: print(類名.mro())
[<class __main__.Son>, <class __main__.Foo>, <class object>]

Python()- 面向對象三大特性----繼承