【python】详解类class的方法解析顺序MRO(Method Resolution Order)(六)

在【python】详解类class的继承、init初始化、super方法(五)详见链接一文中通过super的方法使得子类调用父类的属性或函数方法。正是因为class有方法解析顺序MRO。此文将详解MRO运行逻辑。

  • Python的多继承类是通过MRO的方式来保证各个父类的函数被逐一调用,而且保证每个父类函数只调用一次(如果每个类都使用super)
  • 混用super类和非绑定的函数是一个危险行为,这可能导致应该调用的父类函数没有调用或者一个父类函数被调用多次

假设现在有一个如下的继承结构,首先通过类名显示调用的方式来调用父类的初始化函数:

#父类A,调用时先print:Enter A,再Leave A
class A(object):
    def __init__(self):
        print( "   ->Enter A")
        print( "   <-Leave A" )
#B类继承A类,B的初始化,先print:Enter B;
#再调用A父类的初始化,运行A父类初始化打印E: A,L: A;
#最后L: B。
class B(A):
    def __init__(self):
        print( "  -->Enter B")
        A.__init__(self)
        print ("  <--Leave B")
#C类继承A类,C的初始化,先print:Enter C;
#再调用A父类的初始化,运行A父类初始化打印E: A,L: A;
#最后L: C。
class C(A):
    def __init__(self):
        print (" --->Enter C")
        A.__init__(self)
        print (" <---Leave C")
#D类继承B、C类,先初始化进入D,print:Enter D
#先调用B类进行初始化,运行B类的初始化
#再调用C类进行初始化,运行C类的初始化
#最后打印:Leave D 
class D(B, C):
    def __init__(self):
        print ("---->Enter D")
        B.__init__(self)
        C.__init__(self)
        print( "<----Leave D")

d = D()

输出结果:

#D类继承B、C类,先初始化进入D,print:Enter D
---->Enter D
#先调用B类进行初始化,运行B类的初始化
  -->Enter B
   ->Enter A
   <-Leave A
  <--Leave B
#再调用C类进行初始化,运行C类的初始化
 --->Enter C
   ->Enter A
   <-Leave A
 <---Leave C
#最后打印:Leave D 
<----Leave D

从输出中可以看到,类A的初始化函数被调用了两次,这不是我们想要的结果;我们通过super方式来调用父类的初始化函数:

class A(object):
    def __init__(self):
        print( "   ->Enter A")
        print( "   <-Leave A" )

class B(A):
    def __init__(self):
        print( "  -->Enter B")
        super(B, self).__init__()
        print ("  <--Leave B")
class C(A):
    def __init__(self):
        print (" --->Enter C")
        super(C, self).__init__()
        print (" <---Leave C")
class D(B, C):
    def __init__(self):
        print ("---->Enter D")
        super(D, self).__init__()
        print( "<----Leave D")

d = D()

输出结果:

---->Enter D
  -->Enter B
 --->Enter C
   ->Enter A
   <-Leave A
 <---Leave C
  <--Leave B
<----Leave D

通过输出可以看到,当使用super后,A的初始化函数只能调用了一次。这是由于Python的类有一个_ _mro _ 属性,这个属性中就保存着方法解析顺序。结合上面的例子来看看类D的 _ mro_ _:

print("MRO:", [x.__name__ for x in D.__mro__])

输出结果

MRO: ['D', 'B', 'C', 'A', 'object']
  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值