【python】python多继承调用顺序(MRO/super()/C3算法)

1、MRO和super

  1.1 MRO

    python是支持多继承的语言,在多继承的场景中不同父类可能拥有同名方法,当子类调用该方法时我们要清楚子类调用的是哪个父类的方法,例如下面的设计:

 D调用的foo方法会返回什么?

 

   代码实现:

 
class A(object):
    def foo(self):
        print('I am A')

class B(A):
    pass

class C(A):
    def foo(self):
        print('I am C')

class D(B, C):
    pass

if __name__ == '__main__':
    d = D()
    d.foo() #result: I am C
View Code

   想要知道d.foo()返回什么就必须要知道Python的MRO(Method Resolution Order)方法解析顺序,新式类使用的是C3算法,Python中可以通过__mro__方法得到类的方法解析顺序,也就是C3算法的结果。

   print(D.__mro__)

   结果为:(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)

   方法的顺序为(D,B,C,A,O),回到问题上,d.foo()方法返回的是父类的C的foo()方法,因为D、B都没有foo方法。

  1.2 super()函数

  子类继承父类后,可以完全重写父类的方法而实现我们想要的功能,然而有些时候我们需要在父类方法的基础上加一些功能,我们不能直接修改父类的方法,完全重写又会出现重复代码,而super函数正是为了解决这样的问题。

   需求分析:

   1,他们都是员工

      2,他们有不同的技能

      3,架构师和程序猿和运维工程师技能

   设计如下:

     

   代码实现如下:

11# class Employee(object):
11#     def __init__(self):
12#         print('i am a employee')

05# class Programmer(Employee):
05#    def __init__(self):
06#         print('i am a programmer')
07#(14#)    super(Programmer, self).__init__()
14#         print('i use Python')

08# class OPS(Employee):
08#     def __init__(self):
09#         print('i am a dev ops')
10#         super(OPS, self).__init__()
13#         print('i can monitor all service')

03# class CTO(Programmer, OPS):
03#     def __init__(self):
04#(14#)     super(CTO, self).__init__()
15#          print('Welcome to my world')

01# if __name__ == '__main__':
02#     cto = CTO() 

   输出结果为:

# I am a cto
# I am a programer
# I am a dev ops
# I am a employee
# I can monitor all serivice
# I use Python
# Welcome to my world

   super函数实现了我们的需求,在父类的基础上扩展功能,如果我们在父类的__init__方法新增功能,子类也会添加上,但是从结果来看会很奇怪,下面我们来分析super函数的原理。

   super原理:

   super函数源码:

def super(cls, inst):
    mro = inst.__class__.mro()
    return mro[mro.index(cls) + 1]

  super函数做了两件事

  1,通过mro()方法获取到实例方法的解析顺序。

  2,在mro顺序中返回当前类的下一个类。

  结合我们实例分析   

  调用__mro__查看方法解析顺序

  print(CTO.__mro__)

# (<class '__main__.CTO'>, <class '__main__.Programer'>, <class '__main__.OPS'>, <class '__main__.Employee'>, <type 'object'>)

  顺序是 ['CTO', 'Programer', 'OPS', 'Employee', 'object']

  1.3 C3算法

    pass...

 

参考文献:

http://py.defcoding.com/chapter-3/mro.html

posted @ 2019-08-23 18:29  快乐happy园  阅读(234)  评论(0)    收藏  举报