python中继承的作用以及多重继承的执行顺序

1.继承只会继承父类的方法,不能继承父类的变量
2.要想继承父类的变量,需要执行父类的__init__(self)方法
3.下划线开头的变量或方法,会被认为是受保护的,不能直接点出来,但如果强制打出来的话也一样能用,只是会有警告
4.静态方法中不能使用self,用@staticmethod声明这是一个静态方法
5.关于python中的getter和setter,比较规范的用法是

class Test2:
    @property
    def para1(self):
        return self._para1

    @para1.setter
    def para1(self, value):
        self._para1 = value

    @para1.deleter
    def para1(self):
        del self._para1

if __name__ == '__main__':
    instance = Test2()
    print(instance.para1)
    instance.para1 = 'abc'
    print(instance.para1)
    del instance.para1

当然,你也可以直接用实例.变量 = xxx来修改,但这样不规范

下面进入正题,多重继承的执行顺序

class A(object):
    def __init__(self):
        print('A')
        super(A, self).__init__()
class B(object):
    def __init__(self):
        print('B')
        super(B, self).__init__()
class C(A):
    def __init__(self):
        print('C')
        super(C, self).__init__()
class D(A):
    def __init__(self):
        print('D')
        super(D, self).__init__()
class E(B,C):
    def __init__(self):
        print('E')
        super(E, self).__init__()
class F(C,B,D):
    def __init__(self):
        print('F')
        super(F, self).__init__()
class G(D,B):
    def __init__(self):
        print('G')
        super(G, self).__init__()

if __name__ == '__main__':
    g = G()
    print(G.mro())
    f = F()
    print(F.mro())

执行结果:

G
D
A
B
[<class '__main__.G'>, <class '__main__.D'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
F
C
B
D
A
[<class '__main__.F'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.A'>, <class 'object'>]

1.如果每个类都有正确的写super(X, self).__init__(),那么mro顺序的所有的类的初始化方法都会执行一遍
2.如果中途有的类没有写或错误的写了super(X, self).__init__(),那么会按mro顺序执行到执行完没写的那个类,执行结束。
3.super(X, self)不是必须点__init__(),可以点别的,但一般没有这么做的
4.类名.mro可以得到mro的顺序
5.这种写法可以实现每个类都被执行有且仅有一次。

如何推算mro顺序,这个问题比较复杂,目前我知道比较靠谱的说法是可以用一种所谓的公式计算出来

mro[G](D,B)
=[G]+merge(mro[D]+mro[B]+[D,B])
=[G]+merge([D]+mro[A]+[A]+[B]+[O]+[D,B])
=[G]+merge([D]+[A]+[O]+[A]+[B]+[O]+[D,B])
接下来是提取,提取有个原则,就是所提取的不是所有列表的表尾。如[A,B,C],A是表头,B、C是表尾。提取完成后,从所有的表头删除该数据。
=[G,D]+merge([A]+[O]+[A]+[B]+[O]+[B])
=[G,D,A]+merge([O]+[B]+[O]+[B])
=[G,D,A,B]+merge([O]+[O])
=[G,D,A,B,O]

mro[F](C,B,D)
=[F]+merge(mro[C]+mro[B]+mro[D]+[C,B,D])
=[F]+merge([C]+[A]+[O]+[B]+[O]+[D]+[A]+[O]+[C,B,D])
=[F,C]+merge([A]+[O]+[B]+[O]+[D]+[A]+[O]+[B,D])
=[F,C,B]+merge([A]+[O]+[O]+[D]+[A]+[O]+[D])
=[F,C,B,D]+merge([A]+[O]+[O]+[A]+[O])
=[F,C,B,D,A,O]

也许你会开始怀疑提取顺序的问题,我的猜测是,首先一个原则肯定是按继承顺序来提取的。其次,先找继承的第1个类的子类,再找子类,这种顺序提取,类似于1→1.1→1.2→2→2.1→2.2。但如果发现所继承的多个类都继承了该子类,就不会执行该子类,转而执行下一个继承的类,这么做是为了避免重复执行同一个类的情况。假设1.2=2.2,被1和2都继承了,这时的执行顺序就是1→1.1→2→2.1→1.2(2.2)。

当然知不知道上面的顺序都无所谓,因为类名.mro可以告诉我们正确的顺序,不管你能不能想通,顺序就是这么个顺序,事实已经被设计者确定了。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值