1. 程式人生 > >python D20 多繼承、C3算法、super()

python D20 多繼承、C3算法、super()

沒有 面試 pri order clas fun 擁有 monkey 表示

# 今日大綱
# 1、多繼承
# 繼承:x是一種y的時候,可以使用繼承關系."is a"
# 一個類同時繼承多個類(python, c++)
# eg:孫悟空是猴子,還是神仙,還是妖怪

# 2、經典類的MRO
# 通過樹形結構的深度優先遍歷
# 一條道走到黑(從左往右)

# 3、新式類的MRO(重點、面試題)c3算法
# 先拆分
# 在合並,第一項的頭和後面所有項的身子(除了頭以外的部分)進行比較,如果都沒有就拿出來,如果出現了,就跳過到後一項,後一項查一個完在跳會原來的位置繼續上述動作

# 4、super() (重點)
# 找MRO(新式的)的順序的下一個

# 一、pytohn多繼承
# python支持多繼承,一個類可以擁有多個父類
# class ShenXian: # 神仙
# def fei(self):
# print("神仙都會?")
# class Monkey: # 猴
# def chitao(self):
# print("猴?喜歡吃桃?")
# class SunWukong(ShenXian, Monkey): # 孫悟空是神仙, 同時也是?只猴
# pass
# sxz = SunWukong() # 孫悟
# sxz.chitao() # 會吃桃?
# sxz.fei() # 會?

# 多繼承存在一個問題,當出現兩個父類中出現蟲棉方法的時候,該怎麽辦
# 這就涉及到如何查找父類方法的這麽一個問題,即MRO(method resolution order)
# 問題,在python中這是一個復雜的問題,因為在不同的python版本中使用的是不同的算法來
# 完成MRO的,首先我們能見到的有兩個版本python2/python3
# python2
# 一個交經典類,在python2.2之前,一直使用的是經典類,經典類的在
# 基類的跟如果什麽都不寫,表示繼承xxx
# 一個叫新式類,在python2.2之後出現了新式類,新式類的特點是
# 基類的跟是object

# python3
# python3中使用的都是新式類,如果基類誰都不繼承,拿這個類會默認繼承object

# 二、經典類的MRO
# 經典類的MRO:通過樹形結構的深度優先遍歷 一條道走到黑(從左往右)

# 三、新式類的MRO
# python中的新式類的MRO是采用C3算法來完成的
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 G(E):
pass
class H(G, F):
pass
# 首先我們確定從H開始找,也就是說創建的是H的對象
# 如果重H找,那找到H+H的父類C3,我們設C3算法是L(x)
# L(H) = H + L(G) + L(F) +(GF) = H + (GECA) + (FDBECA) + (GF) = (HGFDBECA) # 特別註意當頭與後面所有項的身子比較時,如果後面身子項出現該項,在跳到下一項,下一項比較一個完在跳回原來的位置以此往復,如果後面項沒有則拿出此項
# L(G) = G + L(E) +(E) = G + (ECA) + E = (GECA)
# L(F) = F + L(D) + L(E) + (DE) = F + (DBCA) + (ECA) +(DE) = (FDBECA)
# L(E) = E + L(C) + L(A) +(CA) = E + (CA) + A + (CA) = (ECA)
# L(D) = D + L(B) + L(C) +BC = D + (BA) + (CA) =(DBCA)
# L(B) = B + L(A) + A = (BA)
# L(C) = C +L(A) +A = (CA)
# H.__mro__可以查看H的C3算法的排列
# print(H.__mro__)
# (<class ‘__main__.H‘>, <class ‘__main__.G‘>, <class ‘__main__.F‘>, <class ‘__main__.D‘>, <class ‘__main__.B‘>, <class ‘__main__.E‘>, <class ‘__main__.C‘>, <class ‘__main__.A‘>, <class ‘object‘>)

# 四、super() 超類
# super()可以幫我們執行MRO中下一個父類的方法,通常super()有兩個使用的地方:
# 1、可以訪問父類構造方法
# 2、當子類方法想調用父類(MRO)中的方法
# 第一種
# class Foo:
# def __init__(self, a, b, c):
# self.a = a
# self.b = b
# self.c = c
#
# class Bar(Foo):
# def __init__(self, a, b, c, d):
# super().__init__(a, b, c) # 訪問?類的構造?法
# self.d = d
# b = Bar(1, 2, 3, 4)
# print(b.__dict__)
# 結果 {‘a‘: 1, ‘b‘: 2, ‘c‘: 3, ‘d‘: 4}
# 這樣就方便子類,不需要寫那麽多,直接用父類的構造幫我們完成一部分代碼

# 第二種
# class Foo:
# def func1(self):
# super().func1() # 此時找的是MRO順序中下?個類的func1()?法
# print("我的?家. 就住在這個屯")
# class Bar:
# def func1(self):
# print("你的?家. 不在這個屯")
#
# class Ku(Foo, Bar):
# def func1(self):
# super().func1() # 此時super找的是Foo
# print("他的?家. 不知道在哪個屯")

# k = Ku() # 先看MRO . KU, FOO, BAR object
# k.func1()
# k2 = Foo() # 此時的MRO. Foo object
# k2.func1() # 報錯 # Foo這個類沒有繼承 直接報錯

# 面試題
# MRO + super ?試題
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
# Incr Pro Add2 Mult HaHa Init
p = Incr(5)
print(p.val)
c = Add2(2)
print(c.val)

# 結果: 分析:復雜的先找出C3排序、一項項往上找
# Add2
# Mult
# 哈哈
# init
# 5.0
# 8.0
# Add2
# init
# 2
# 4

python D20 多繼承、C3算法、super()