经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Python » 查看文章
继承
来源:cnblogs  作者:尝试了就好  时间:2018/11/14 10:03:03  对本文有异议

一、判断继承

1. issubclass

  • 判断xxx类是否是yyy类型的子类
  • 可以隔代判数
  1. class Base:
  2. pass
  3.  
  4. class Foo(Base):
  5. pass
  6.  
  7. class Bar(Foo):
  8. pass
  9.  
  10. print(issubclass(Bar, Foo)) # True
  11. print(issubclass(Foo, Bar)) # False
  12. print(issubclass(Bar, Base)) # True

 二、多继承

  • python支持多继承,一个类可以拥有多个父类
  • 经典类:在python2.2之前版本使用的是经典类,经典类在基类的根如果什么都不写,不示继承xxx
  • 新式类:在python2.2之后版本使用的是新式类,新式类的特点是基类的根是object
  • python3使用的都是新式类,如果基类谁都不继承。那这个类会默认继承object

三、MRO

    在多继承中,当多个父类出现了重名方法时,此时就涉及到如何查找父类方法的问题,即MRO(method resolution order)问题。

    在python中,不同的版本中使用的是不同的算法来完成MRO的

1. 经典类的MRO

  • 采用的是树型结构的深度优先遍历
  • 深度优先遍历:从左往右,一条道走到黑
  1. class A:
  2. pass
  3.  
  4. class B(A):
  5. pass
  6.  
  7. class C(A):
  8. pass
  9.  
  10. class D(B, C):
  11. pass
  12.  
  13. class E:
  14. pass
  15.  
  16. class F(E, B):
  17. pass
  18.  
  19. class G(F, D):
  20. pass
  21.  
  22. class H:
  23. pass
  24.  
  25. class Foo(H, G):
  26. pass

 继承关系图如下:

 

图1  继承关系图

类的MRO:Foo ---> H ---> G ---> F ---> E ---> B ---> A --->D ---> C

2. 新式类的MRO—C3算法

步骤:

  • 先拆分
  • 再合并:从下向上合并,拿出每一项的头和后一项的身体进行比较,如果出现了,就过,从后一项的头继续去比较,如果不出现就拿出来
  1. class A:
  2. pass
  3. class B(A):
  4. pass
  5. class C(A):
  6. pass
  7. class D(B, C):
  8. pass
  9. class E(C, A):
  10. pass
  11. class F(D, E):
  12. pass
  13. class M(F, E):
  14. pass
  15. class N:
  16. pass
  17. class P(M,N):
  18. pass
  19. class G(P):
  20. pass
  21. class O:
  22. pass
  23. class X(O):
  24. pass
  25. class H(G, X, F):
  26. pass
  27. 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顺序

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

 

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

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

四、super

1. 访问父类的初始化方法

    这样子类和父类初始化方法中相同的代码可不必都写,直接用父类的就好

  1. class Base(object):
  2. def __init__(self, a, b, c):
  3. self.a = a
  4. self.b = b
  5. self.c = c
  6. class Foo(Base):
  7. def __init__(self, a, b, c, d):
  8. super().__init__(a, b, c)
  9. self.d = d
  10. f = Foo(1, 2, 3, 4)
  11. print(vars(f)) # {'a': 1, 'b': 2, 'c': 3, 'd': 4}

 

2. 实现子类方法调用父类(MRO)中的方法

  • super().方法名():执行MRO中下一个方法
  • super(类名,self).方法名():定位到该类,执行MRO中该类下一个类的方法
  1. class Biology(object):
  2. def move(self):
  3. print("----biology-----")
  4. class Animal(Biology):
  5. def move(self):
  6. print("-----Animal-----")
  7. class Cat(Animal):
  8. def move(self):
  9. super().move() # 找MRO中的下一个
  10. print("-----Cat-----")
  11. c = Cat()
  12. c.move()
  13. # 结果:
  14. # -----Animal-----
  15. # -----Cat-----

 

  1. class Biology(object):
  2. def move(self):
  3. print("----biology-----")
  4. class Animal(Biology):
  5. def move(self):
  6. print("-----Animal-----")
  7. class Cat(Animal):
  8. def move(self):
  9. super(Animal, self).move() # 定位到Animal,找Animal下一个
  10. print("-----Cat-----")
  11. c = Cat()
  12. c.move()
  13. # 结果:
  14. # ----biology-----
  15. # -----Cat-----

 

3. 应用

  1. class Init(object):
  2. def __init__(self, v):
  3. print("init")
  4. self.val = v
  5. class Add2(Init):
  6. def __init__(self, val):
  7. print("Add2")
  8. super(Add2, self).__init__(val)
  9. print(self.val)
  10. self.val += 2
  11.  
  12.  
  13. class Mult(Init):
  14. def __init__(self, val):
  15. print("Mult")
  16. super(Mult, self).__init__(val)
  17. self.val *= 5
  18.  
  19.  
  20. class HaHa(Init):
  21. def __init__(self, val):
  22. print("哈哈")
  23. super(HaHa, self).__init__(val)
  24. self.val /= 5
  25.  
  26.  
  27. class Pro(Add2,Mult,HaHa): #
  28. pass
  29.  
  30.  
  31. class Incr(Pro):
  32. def __init__(self, val):
  33. super(Incr, self).__init__(val)
  34. self.val += 1
  35. p = Incr(5)
  36. 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

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号