繼承

1、判斷繼承

1. issubclass

  • 判斷xxx類是不是yyy類型的子類
  • 能夠隔代判數
class Base:
    pass

class Foo(Base):
    pass

class Bar(Foo):
    pass

print(issubclass(Bar, Foo))   # True
print(issubclass(Foo, Bar))   # False
print(issubclass(Bar, Base))  # True

 2、多繼承

  • python支持多繼承,一個類能夠擁有多個父類
  • 經典類:在python2.2以前版本使用的是經典類,經典類在基類的根若是什麼都不寫,表示繼承xxx
  • 新式類:在python2.2以後版本使用的是新式類,新式類的特色是基類的根是object
  • python3使用的都是新式類,若是基類誰都不繼承。那這個類會默認繼承object

3、MRO

    在多繼承中,當多個父類出現了重名方法時,此時就涉及到如何查找父類方法的問題,即MRO(method resolution order)問題。python

    在python中,不一樣的版本中使用的是不一樣的算法來完成MRO的算法

1. 經典類的MRO

  • 採用的是樹型結構的深度優先遍歷(先序),即根-左-右。
class A:
    pass

class B(A):
    pass

class C(A):
    pass

class D(B, C):
    pass

class E:
    pass

class F(E, B):
    pass

class G(F, D):
    pass

class H:
    pass

class Foo(H, G):
    pass

 繼承關係圖以下:spa

 

圖1  繼承關係圖code

類的MRO:Foo ---> H ---> G ---> F ---> E ---> B ---> A --->D ---> Cblog

2. 新式類的MRO—C3算法

官方網址:https://www.python.org/download/releases/2.3/mro/?tdsourcetag=s_pctim_aiomsg繼承

步驟:get

  • 先拆分
  • 再合併:從下向上合併,拿出每一項的頭和後一項的身體進行比較,若是出現了,就過,從後一項的頭繼續去比較,若是不出現就拿出來
class A:
    pass
class B(A):
    pass
class C(A):
    pass
class D(B, C):
    pass
class E(C, A):
    pass
class F(D, E):
    pass
class M(F, E):
    pass
class N:
    pass
class P(M,N):
    pass
class G(P):
    pass
class O:
    pass
class X(O):
    pass
class H(G, X, F):
    pass
print(H.__mro__)

結果:
(<class '__main__.H'>, <class '__main__.G'>, <class '__main__.P'>, <class '__main__.M'>, <class '__main__.X'>, <class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class '__main__.N'>, <class '__main__.O'>, <class 'object'>)

1) 先拆分:設L爲查找方法的MRO順序it

L(H) = H + L(G) + L(X) + L(F) + GXFio

 

L(G) = G + L(P) + Pclass

L(X) = X + L(O) + O

L(F) = F + L(D) + L(E) + DE

 

L(P) = P + L(M) + L(N) + MN

L(D) = D + L(B) + L(C) + BC

L(E) = E + L(C) + A + CA

 

L(M) = M + L(F) + L(E) + FE

2) 合併:

L(H) = H + L(G) + L(X) + L(F) + GXF     ====>HGPMXFDBECANO

 

L(G) = G + L(P) + P                                ====>GPMFDBECAN

L(X) = X + L(O) + O                                ====>XO

L(F) = F + L(D) + L(E) + DE                   ====>FDBECA

 

L(P) = P + L(M) + L(N) + MN                 ====>PMFDBECAN

L(D) = D + L(B) + L(C) + BC                  ====>DBCA

L(E) = E + L(C) + A + CA                       ====>ECA

 

L(M) = M + L(F) + L(E) + FE                  ====>MFDBECA

L(C) = C + L(A)                                     ====>CA

L(N) = N                                               ====>N

L(B) = B + L(A) + A                              ====>BA

類的MRO:H--->G--->P--->M--->X--->F--->D--->B--->E--->C--->A--->N--->O

4、super

1. 訪問父類的初始化方法

    這樣子類和父類初始化方法中相同的代碼可沒必要都寫,直接用父類的就好

class Base(object):

    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c


class Foo(Base):

    def __init__(self, a, b, c, d):
        super().__init__(a, b, c)
        self.d = d


f = Foo(1, 2, 3, 4)
print(vars(f))    # {'a': 1, 'b': 2, 'c': 3, 'd': 4}

 

2. 實現子類方法調用父類(MRO)中的方法

  • super().方法名():執行MRO中下一個方法
  • super(類名,self).方法名():定位到該類,執行MRO中該類下一個類的方法
class Biology(object):
    def move(self):
        print("----biology-----")


class Animal(Biology):
    def move(self):
        print("-----Animal-----")


class Cat(Animal):
    def move(self):
        super().move()   # 找MRO中的下一個
        print("-----Cat-----")


c = Cat()
c.move()


# 結果:
# -----Animal-----
# -----Cat-----

 

class Biology(object):
    def move(self):
        print("----biology-----")


class Animal(Biology):
    def move(self):
        print("-----Animal-----")


class Cat(Animal):
    def move(self):
        super(Animal, self).move()   # 定位到Animal,找Animal下一個
        print("-----Cat-----")


c = Cat()
c.move()


# 結果:
# ----biology-----
# -----Cat-----

 

3. 應用

class Init(object):
    def __init__(self, v):
        print("init")
        self.val = v


class Add2(Init):
    def __init__(self, val):
        print("Add2")
        super(Add2, self).__init__(val)
        print(self.val)
        self.val += 2


class Mult(Init):
    def __init__(self, val):
        print("Mult")
        super(Mult, self).__init__(val)
        self.val *= 5


class HaHa(Init):
    def __init__(self, val):
        print("哈哈")
        super(HaHa, self).__init__(val)
        self.val /= 5


class Pro(Add2,Mult,HaHa): #
    pass


class Incr(Pro):
    def __init__(self, val):
        super(Incr, self).__init__(val)
        self.val += 1


p = Incr(5)
print(p.val)   # Add2 Mult 哈哈 init 5.0 8.0

c = Add2(2)

print(c.val) # Add2 init 2 4

 

MRO:

1)  Incr: Incr ---> Pro ---> Add2 ---> Mult ---> HaHa ---> Init

2) Add2: Add2 ---> Init

相關文章
相關標籤/搜索