1. 程式人生 > >Day31:繼承實現的原理

Day31:繼承實現的原理

class 調用 rom 類的方法 gif 兩個 屬性 -h 使用

一、繼承實現的原來

1、繼承順序

Python的類可以繼承多個類。繼承多個類的時候,其屬性的尋找的方法有兩種,分別是深度優先廣度優先

如下的結構,新式類和經典類的屬性查找順序都一致。順序為D--->A--->E--->B--->C。

技術分享

class E:
    def test(self):
        print(from E)
class A(E):
    def test(self):
        print(from A)
class B:
    def test(self):
        print(from B)
class
C: def test(self): print(from C) class D(A,B,C): def test(self): print(from D) d=D() d.test() print(D.mro()) #新式類才可以查看.mro()方法查看查找順序 ‘‘‘ from D [<class ‘__main__.D‘>, <class ‘__main__.A‘>, <class ‘__main__.E‘>, <class ‘__main__.B‘>, <class ‘__main__.C‘>, <class ‘object‘>]
‘‘‘

如下的結構,新式類和經典類的屬性查找順序就不一樣了。

經典類遵循深度優先,其順序為:F--->E--->B--->A--->F--->C--->G--->D

新式類遵循廣度優先,其順序為:F--->E--->B--->F--->C--->G--->D--->A

技術分享

2、繼承原理

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

print(D.mro())
‘‘‘
[<class ‘__main__.D‘>, <class ‘__main__.A‘>, <class ‘__main__.E‘>, <class ‘__main__.B‘>, <class ‘__main__.C‘>, <class ‘object‘>]
‘‘‘

為了實現繼承,python會在MRO列表上從左到右開始查找基類,直到找到第一個匹配這個屬性的類為止。
而這個MRO列表的構造是通過一個C3線性化算法來實現的。我們不去深究這個算法的數學原理,它實際上就是合並所有父類的MRO列表並遵循如下三條準則:
1.子類會先於父類被檢查。
2.多個父類會根據它們在列表中的順序被檢查。
3.如果對下一個類存在兩個合法的選擇,選擇第一個父類。

二、子類中調用父類的方法

子類繼承了父類的方法,然後想進行修改,註意了是基於原有的基礎上修改,那麽就需要在子類中調用父類的方法。

方法一:父類名.父類方法()

技術分享
#_*_coding:utf-8_*_

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)

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

方法二: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) 就相當於實例本身 在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()
View Code

不用super引發的慘案

#每個類中都繼承了且重寫了父類的方法
class A:
    def __init__(self):
        print(A的構造方法)
        
class B(A):
    def __init__(self):
        print(B的構造方法)
        A.__init__(self)
class C(A):
    def __init__(self):
        print(C的構造方法)
        A.__init__(self)
        
class D(B,C):
    def __init__(self):
        print(D的構造方法)
        B.__init__(self)
        C.__init__(self)
f1=D()
print(D.__mro__) 
‘‘‘
D的構造方法
B的構造方法
A的構造方法
C的構造方法
A的構造方法
(<class ‘__main__.D‘>, <class ‘__main__.B‘>, <class ‘__main__.C‘>, <class ‘__main__.A‘>, <class ‘object‘>)
‘‘‘

使用super()的結果

class A:
    def __init__(self):
        print(A的構造方法)

class B(A):
    def __init__(self):
        print(B的構造方法)
        super().__init__()    #super(B,self).__init__()
class C(A):
    def __init__(self):
        print(C的構造方法)
        super().__init__()    #super(C,self).__init__()

class D(B,C):
    def __init__(self):
        print(D的構造方法)
        super().__init__()    #super(D,self).__init__()
        # C.__init__(self)
f1=D()
print(D.__mro__)
‘‘‘
D的構造方法
B的構造方法
C的構造方法
A的構造方法
(<class ‘__main__.D‘>, <class ‘__main__.B‘>, <class ‘__main__.C‘>, <class ‘__main__.A‘>, <class ‘object‘>)
‘‘‘

當你使用super()函數時,Python會在MRO列表上繼續搜索下一個類。只要每個重定義的方法統一使用super()並只調用它一次,那麽控制流最終會遍歷完整個MRO列表,每個方法也只會被調用一次(註意註意註意:使用super調用的所有屬性,都是從MRO列表當前的位置往後找,千萬不要通過看代碼去找繼承關系,一定要看MRO列表

三、

Day31:繼承實現的原理